টেল কল অপ্টিমাইজেশন অনেক ভাষা এবং সংকলক উপস্থিত in এই পরিস্থিতিতে, সংকলক ফর্মের একটি কার্য স্বীকৃতি দেয়:
int foo(n) {
...
return bar(n);
}
এখানে ভাষাটি চিনতে সক্ষম হয়েছে যে ফলাফলটি ফেরত দেওয়া হচ্ছে অন্য ফাংশন থেকে প্রাপ্ত ফলাফল এবং একটি নতুন স্ট্যাক ফ্রেমের সাহায্যে একটি ফাংশন কলকে একটি জাম্পে পরিবর্তন করতে হবে।
ক্লাসিক কল্পিত পদ্ধতিটি অনুধাবন করুন:
int factorial(n) {
if(n == 0) return 1;
if(n == 1) return 1;
return n * factorial(n - 1);
}
হয় না পরিদর্শন আগমন প্রয়োজনীয় কারণ লেজ কল optimizatable। ( উত্স কোড এবং সংকলিত আউটপুট উদাহরণ )
এই লেজ কলটি অনুকূলিত করে তুলতে,
int _fact(int n, int acc) {
if(n == 1) return acc;
return _fact(n - 1, acc * n);
}
int factorial(int n) {
if(n == 0) return 1;
return _fact(n, 1);
}
এই কোডটি gcc -O2 -S fact.c
সংকলন করে (-O2 সংকলকটিতে অপ্টিমাইজেশন সক্ষম করার জন্য প্রয়োজনীয়, তবে -O3 এর আরও অনুকূলিতকরণের সাথে এটি মানুষের পক্ষে পড়া শক্ত হয়ে যায় ...)
_fact(int, int):
cmpl $1, %edi
movl %esi, %eax
je .L2
.L3:
imull %edi, %eax
subl $1, %edi
cmpl $1, %edi
jne .L3
.L2:
rep ret
( উত্স কোড এবং সংকলিত আউটপুট উদাহরণ )
একটি অংশ দেখতে পাবেন .L3
, jne
বরং একটি তুলনায় call
(যা একটি নতুন স্ট্যাক ফ্রেম সঙ্গে একটি সাবরুটিন কল না)।
দয়া করে নোট করুন যে এটি সি দ্বারা করা হয়েছিল জাভাতে টেইল কল অপ্টিমাইজেশন হার্ড এবং এটি জেভিএম বাস্তবায়নের উপর নির্ভর করে (এটি বলেছে যে, আমি এটি করে এমন কোনও কিছুই দেখিনি, কারণ এটি স্ট্যাঙ্ক ফ্রেমের জন্য প্রয়োজনীয় জাভা সুরক্ষা মডেলের কঠোর এবং জড়িত বিষয়গুলি) - যা টিসিও এড়িয়ে চলে) - টেল-পুনরাবৃত্তি + জাভা এবং লেজ-পুনরাবৃত্তি + অপ্টিমাইজেশন ব্রাউজ করার জন্য ভাল ট্যাগ সেট। আপনি অন্যান্য জেভিএম ভাষাগুলি লেজ পুনরাবৃত্তিকে আরও অনুকূল করতে সক্ষম হবেন (ক্লোজারটি (যার জন্য টেল কলটি অপ্টিমাইজ করতে পুনরাবৃত্তির প্রয়োজন )) বা স্কালা)।
বলেছিল,
আপনি সঠিক কিছু লিখেছিলেন তা জেনে একটি আনন্দ রয়েছে - আদর্শ উপায়ে এটি করা যায়।
এবং এখন, আমি কিছু স্কচ পেতে যাচ্ছি এবং কিছু জার্মান ইলেক্ট্রনিকা দেব ...
"পুনরাবৃত্তিমূলক অ্যালগরিদমে স্ট্যাকের ওভারফ্লো এড়ানোর জন্য পদ্ধতিগুলির" সাধারণ প্রশ্নের কাছে ...
আর একটি পদ্ধতির পুনরাবৃত্তি কাউন্টার অন্তর্ভুক্ত করা হয়। এটি নিজের নিয়ন্ত্রণের বাইরে অবস্থার কারণে (এবং খারাপ কোডিং) অসীম লুপগুলি সনাক্ত করার জন্য আরও বেশি।
পুনরাবৃত্তি কাউন্টার রূপ নেয়
int foo(arg, counter) {
if(counter > RECURSION_MAX) { return -1; }
...
return foo(arg, counter + 1);
}
প্রতিবার আপনি যখন কল করবেন তখন আপনি কাউন্টারটি বাড়িয়ে তুলবেন। যদি কাউন্টারটি খুব বড় হয়ে যায়, আপনি ত্রুটিযুক্ত হয়ে যান (এখানে, -1 এর মাত্র একটি রিটার্ন, যদিও অন্যান্য ভাষায় আপনি ব্যতিক্রম ছুঁড়তে পছন্দ করতে পারেন)। ধারণাটি হ'ল প্রত্যাশার চেয়ে অনেক গভীর এবং সম্ভবত অসীম লুপটি যখন পুনরাবৃত্তি করতে গিয়ে খারাপ জিনিসগুলি ঘটে (স্মৃতি ত্রুটির বাইরে থাকে) না ঘটে।
তত্ত্বীয়ভাবে, আপনার এটির দরকার নেই। অনুশীলনে, আমি দুর্বল লিখিত কোড দেখেছি যা ছোট ত্রুটি এবং খারাপ কোডিং অনুশীলনের আধিক্যের কারণে এটি হিট হয়েছে (বহুবিবাহিত একত্রিত ইস্যু যেখানে পদ্ধতির বাইরে কিছু পরিবর্তিত হয় যা অন্য থ্রেডকে পুনরাবৃত্ত কলগুলির অসীম লুপে ফেলে দেয়)।
সঠিক অ্যালগরিদম ব্যবহার করুন এবং সঠিক সমস্যাটি সমাধান করুন। বিশেষত কোলাটজ কনজেকচারের জন্য, এটি xxcd উপায়ে সমাধান করার চেষ্টা করছেন বলে মনে হয় :
আপনি একটি নম্বর থেকে শুরু করছেন এবং একটি ট্রি ট্রভারসাল করছেন। এটি দ্রুত খুব বড় অনুসন্ধানের দিকে নিয়ে যায়। প্রায় 500 টি পদক্ষেপে সঠিক উত্তরের ফলাফলের জন্য পুনরাবৃত্তির সংখ্যা গণনা করার জন্য একটি দ্রুত রান। এটি একটি ছোট স্ট্যাক ফ্রেমের সাথে পুনরাবৃত্তির জন্য সমস্যা হওয়া উচিত নয়।
যদিও পুনরাবৃত্তির সমাধানটি জানা কোনও খারাপ জিনিস নয়, তবে এটিরও বুঝতে হবে যে বহুবার পুনরাবৃত্তি সমাধানটি ভাল । পুনরাবৃত্তির ক্ষেত্রে পুনরাবৃত্তির অ্যালগরিদমকে রূপান্তরিত করার বিভিন্ন উপায়ের পুনরাবৃত্তি থেকে পুনরাবৃত্তিতে যাওয়ার জন্য স্ট্যাক ওভারফ্লোতে দেখা যায় ।