আলস্য
এটি একটি "সংকলক অপ্টিমাইজেশন" নয়, তবে এটি ভাষা স্পেসিফিকেশন দ্বারা গ্যারান্টিযুক্ত এমন কিছু, যাতে আপনি সর্বদা এটির উপর নির্ভর করতে পারেন। মূলত, এর অর্থ হল যে ফলাফলটি আপনি "কিছু না করা" না হওয়া পর্যন্ত কাজ করা হয় না। (যদি না আপনি ইচ্ছাকৃতভাবে অলসতা বন্ধ করার জন্য কয়েকটি কাজ না করেন))
এটি অবশ্যই স্পষ্টতই একটি নিজস্ব বিষয় এবং এটির বিষয়ে ইতিমধ্যে প্রচুর প্রশ্নোত্তর রয়েছে।
আমার সীমিত অভিজ্ঞতায়, আপনার কোডটি খুব অলস বা খুব কঠোর করে তোলার বিষয়ে আমি কথা বলার মতো অন্য যে কোনও স্টাফের তুলনায় (সময় এবং স্থানের ক্ষেত্রে) বিশাল আকারের পারফরম্যান্স পেনাল্টি পেয়েছি ...
কঠোরতা বিশ্লেষণ
অলসতা প্রয়োজনীয়তা না থাকলে কাজ এড়ানো সম্পর্কে। যদি সংকলক নির্ধারণ করতে পারে যে প্রদত্ত ফলাফলটি "সর্বদা" প্রয়োজন হবে, তবে এটি গণনাটি সংরক্ষণ এবং পরে সম্পাদনকে বিরক্ত করবে না; এটি কেবল এটি সম্পাদন করবে, কারণ এটি আরও দক্ষ। এটি তথাকথিত "কঠোরতা বিশ্লেষণ"।
স্পষ্টতই, গোচা হ'ল কম্পাইলারটি সর্বদা সনাক্ত করতে পারে না যে কখন কোনও কিছু কঠোর করা যায়। কখনও কখনও আপনাকে সংকলকটিকে সামান্য ইঙ্গিত দেওয়া দরকার। (কোর আউটপুটটি ভ্যাডিং বাদে কঠোরতা বিশ্লেষণ আপনার যা মনে হয়েছে তা করেছে কিনা তা নির্ধারণের কোনও সহজ উপায় সম্পর্কে আমি অবগত নই।)
ইনলাইনিং
আপনি যদি কোনও ফাংশন কল করেন এবং সংকলকটি আপনাকে বলতে পারে যে আপনি কোন ফাংশনটি কল করছেন, এটি সেই ফাংশনটির "ইনলাইন" করার চেষ্টা করতে পারে - এটি ফাংশনের কলটিকে নিজেই একটি অনুলিপি দিয়ে প্রতিস্থাপন করতে পারে। একটি ফাংশন কলের ওভারহেড সাধারণত খুব ছোট হয় তবে ইনলাইনিং প্রায়শই অন্যান্য অপটিমাইজেশনগুলিকে সক্ষম করে যা অন্যথায় ঘটে না, তাই ইনলাইনিং একটি বড় জয় হতে পারে।
যদি সেগুলি "যথেষ্ট পরিমাণে ছোট" হয় তবেই (বা আপনি যদি বিশেষত ইনলাইনিংয়ের জন্য জিজ্ঞাসাবাদ যুক্ত করেন) তবে কার্যাদি কেবল ইনলাইন করা হয়। এছাড়াও, ফাংশনগুলি কেবল তখনই ইনলাইন করা যেতে পারে যদি সংকলকটি আপনাকে বলতে পারে যে ফাংশনটি কল করছেন। দুটি প্রধান উপায় আছে যা সংকলকটি বলতে অক্ষম হতে পারে:
আপনি যে ফাংশনটি কল করছেন সেটি যদি অন্য কোথাও থেকে পাস করা হয়। উদাহরণস্বরূপ, filter
ফাংশনটি সংকলিত হয়ে গেলে আপনি ফিল্টার প্রিকিকেট ইনলাইন করতে পারবেন না, কারণ এটি একটি ব্যবহারকারী সরবরাহিত যুক্তি।
যদি আপনি যে ফাংশনটি কল করছেন সেটি কোনও শ্রেণিবদ্ধ পদ্ধতি এবং সংকলকটি কী প্রকারের সাথে জড়িত তা জানেন না। উদাহরণস্বরূপ, sum
ফাংশনটি সংকলিত হয়ে গেলে , সংকলকটি +
ফাংশনটি ইনলাইন করতে পারে না , কারণ sum
বিভিন্ন সংখ্যার ধরণের সাথে কাজ করে, যার প্রত্যেকটির একটি আলাদা +
ফাংশন রয়েছে।
পরবর্তী ক্ষেত্রে, আপনি {-# SPECIALIZE #-}
প্রাগমা ব্যবহার করতে পারেন কোনও নির্দিষ্ট ধরণের হার্ড-কোডড এমন কোনও ফাংশনের সংস্করণ তৈরি করতে। উদাহরণস্বরূপ, প্রকারের জন্য হার্ড {-# SPECIALIZE sum :: [Int] -> Int #-}
কোডিংয়ের একটি সংস্করণ সংকলন করবে , যার অর্থ এই সংস্করণে অন্তর্ভুক্ত করা যেতে পারে।sum
Int
+
নোট করুন, যদিও, আমাদের নতুন বিশেষ sum
ফাংশনটি কেবল তখনই ডাকা হবে যখন সংকলক বলতে পারবে যে আমরা কাজ করছি Int
। অন্যথায় আসল, পলিমারফিক sum
বলা হয়। আবার, আসল ফাংশন কল ওভারহেড মোটামুটি ছোট। এটি অতিরিক্ত অপটিমাইজেশন যা ইনলাইনিং সক্ষম করে যা উপকারী।
প্রচলিত subexpression নির্মূল
কোডের একটি নির্দিষ্ট ব্লক যদি একই মানকে দুবার গণনা করে তবে সংকলক একই সংখ্যার একক উদাহরণ দিয়ে প্রতিস্থাপন করতে পারে। উদাহরণস্বরূপ, যদি আপনি করেন
(sum xs + 1) / (sum xs + 2)
তারপরে সংকলক এটি এটিকে অনুকূল করতে পারে
let s = sum xs in (s+1)/(s+2)
আপনি আশা করতে পারেন যে সংকলকটি সর্বদা এটি করবে । তবে আপাতদৃষ্টিতে কিছু পরিস্থিতিতে এর খারাপ পরিণতি হতে পারে, আরও ভাল নয়, তাই GHC সর্বদা এটি করে না । সত্যই, আমি এর পিছনে বিশদটি সত্যই বুঝতে পারি না। তবে নীচের অংশটি হ'ল, যদি এই রূপান্তরটি আপনার পক্ষে গুরুত্বপূর্ণ হয় তবে ম্যানুয়ালি এটি করা কঠিন নয়। (এবং যদি এটি গুরুত্বপূর্ণ না হয় তবে আপনি কেন এটি নিয়ে উদ্বিগ্ন হন?)
কেস এক্সপ্রেশন
নিম্নোক্ত বিবেচনা কর:
foo (0:_ ) = "zero"
foo (1:_ ) = "one"
foo (_:xs) = foo xs
foo ( []) = "end"
প্রথম তিনটি সমীকরণ সমস্ত তালিকাটি খালি নয় কিনা (অন্যান্য জিনিসের মধ্যে) পরীক্ষা করে। তবে তিনবার একই জিনিস পরীক্ষা করা ব্যর্থ। ভাগ্যক্রমে, সংকলকটির পক্ষে এটি বেশ কয়েকটি নেস্টেড কেস এক্সপ্রেশনগুলিতে অনুকূলিত করা খুব সহজ। এই ক্ষেত্রে, মত কিছু
foo xs =
case xs of
y:ys ->
case y of
0 -> "zero"
1 -> "one"
_ -> foo ys
[] -> "end"
এটি বরং স্বল্পতর স্বজ্ঞাত, তবে আরও দক্ষ। যেহেতু সংকলক সহজেই এই রূপান্তরটি করতে পারে, আপনার এটি নিয়ে চিন্তা করার দরকার নেই। সর্বাধিক স্বজ্ঞাত উপায়ে আপনার প্যাটার্নের মিলটি কেবল লিখুন; এটিকে যত তাড়াতাড়ি করা যায় তার জন্য সংকলকটি এর পুনঃক্রম এবং পুনঃব্যবস্থাপনে খুব ভাল।
একীকরণ
তালিকা প্রক্রিয়াকরণের জন্য স্ট্যান্ডার্ড হাস্কেল আইডিয়ম হ'ল ফাংশনগুলি একসাথে চেইন করা যা একটি তালিকা নিয়ে এবং একটি নতুন তালিকা তৈরি করে। ক্যানোনিকাল উদাহরণ হচ্ছে
map g . map f
দুর্ভাগ্যক্রমে, অলসতা যখন অপ্রয়োজনীয় কাজগুলি এড়িয়ে যাওয়ার নিশ্চয়তা দেয়, তখন মধ্যবর্তী তালিকার এসএপি কর্মক্ষমতা জন্য সমস্ত বরাদ্দ এবং বিলোপ। "ফিউশন" বা "বনভূমি" যেখানে সংকলক এই মধ্যবর্তী পদক্ষেপগুলি মুছে ফেলার চেষ্টা করে।
সমস্যাটি হচ্ছে, এই ফাংশনগুলির বেশিরভাগই পুনরাবৃত্ত হয়। পুনরাবৃত্তি ছাড়াই, এটি সমস্ত ফাংশনকে একটি বড় কোড ব্লকে স্কোয়াশ করা, তার উপর সরলীকরণকারী চালানো এবং কোনও মধ্যবর্তী তালিকা ছাড়াই সত্যিকারের অনুকূল কোড উত্পাদন করা ইনলাইনিংয়ের প্রাথমিক অনুশীলন হবে। তবে পুনরাবৃত্তি হওয়ার কারণে এটি কার্যকর হবে না।
এর {-# RULE #-}
কয়েকটি ঠিক করার জন্য আপনি প্রাগমাস ব্যবহার করতে পারেন । উদাহরণ স্বরূপ,
{-# RULES "map/map" forall f g xs. map f (map g xs) = map (f.g) xs #-}
এখন প্রতিবার জিএইচসি map
আবেদন করে দেখলে map
এটি মধ্যবর্তী তালিকাটি বাদ দিয়ে তালিকার একক পাসে এটিকে স্কোয়াশ করে।
সমস্যা হচ্ছে, এটি কেবল map
অনুসরণের জন্য কাজ করে map
। - অনেক অন্যান্য সম্ভাবনা আছে map
দ্বারা অনুসরণ filter
, filter
দ্বারা অনুসরণ map
, ইত্যাদি বরং হাতে কোড তাদের প্রতিটি জন্য একটি সমাধান, তথাকথিত "স্ট্রিম লয়" আবিষ্কৃত হয়। এটি আরও জটিল কৌশল, যা আমি এখানে বর্ণনা করব না।
এর দীর্ঘ এবং সংক্ষিপ্তটি হ'ল: এগুলি প্রোগ্রামার দ্বারা রচিত সমস্ত বিশেষ অপ্টিমাইজেশনের কৌশল । জিএইচসি নিজেই ফিউশন সম্পর্কে কিছুই জানে না; এটি সমস্ত তালিকা গ্রন্থাগার এবং অন্যান্য ধারক লাইব্রেরিতে রয়েছে। সুতরাং কী কী অপ্টিমাইজেশান ঘটে তা নির্ভর করে কীভাবে আপনার ধারক লাইব্রেরিগুলি লেখা হয় (বা আরও বাস্তবসম্মতভাবে আপনি কোন লাইব্রেরিগুলি ব্যবহার করতে চান) তার উপর নির্ভর করে।
উদাহরণস্বরূপ, যদি আপনি হাস্কেল '98 অ্যারে নিয়ে কাজ করেন তবে কোনও প্রকারের কোনও ফিউশন আশা করবেন না। তবে আমি বুঝতে পারি যে vector
লাইব্রেরির বিস্তীর্ণ ফিউশন ক্ষমতা রয়েছে। এটি সমস্ত গ্রন্থাগার সম্পর্কে; সংকলক কেবল RULES
প্রগমা সরবরাহ করে । (যা অত্যন্ত শক্তিশালী, যাইহোক। একটি গ্রন্থাগারের লেখক হিসাবে, আপনি এটি ক্লায়েন্ট কোডটি পুনরায় লেখার জন্য ব্যবহার করতে পারেন!)
meta:
আমি "কোডটি প্রথম, প্রোফাইল দ্বিতীয়, তৃতীয়টিকে অনুকূলিতকরণ" বলার সাথে সম্মত agree
আমি লোকদের সাথেও একমত হয়ে বলি "প্রদত্ত ডিজাইনের সিদ্ধান্তের জন্য কতটা ব্যয় হয়েছে তার মানসিক মডেল রাখাই দরকারী"।
সমস্ত কিছুর মধ্যে ভারসাম্য, এবং ...