টেল-কল পুনরাবৃত্তির জন্য। নেট / সি # অনুকূলিত হয় না কেন?


111

কোন ভাষাগুলির লেজ পুনরাবৃত্তি অনুকূলিত করে সে সম্পর্কে এই প্রশ্নটি পেয়েছি । কেন যখনই সম্ভব সি # লেজ পুনরাবৃত্তি অপ্টিমাইজ করে না?

একটি কংক্রিট ক্ষেত্রে, কেন এই পদ্ধতিটি কোনও লুপে অনুকূলিত করা হয়নি ( ভিজ্যুয়াল স্টুডিও ২০০২ 32-বিট, যদি তা বিবেচনা করে তবে) ?:

private static void Foo(int i)
{
    if (i == 1000000)
        return;

    if (i % 100 == 0)
        Console.WriteLine(i);

    Foo(i+1);
}

আমি আজ ডেটা স্ট্রাকচারের উপর একটি বই পড়ছিলাম যা পুনরাবৃত্ত ফাংশনকে দু'টি preemptive(যেমন ফ্যাকটোরিয়াল অ্যালগরিদম) এবং Non-preemptive(যেমন আকারম্যানের ফাংশন) বিভক্ত করে তোলে। এই দ্বিখণ্ডনের পিছনে যথাযথ যুক্তি না দিয়ে লেখক মাত্র দুটি উদাহরণ দিয়েছিলেন। এই বিভাজনটি কি লেজ এবং নন-লেজ ​​পুনরাবৃত্ত ফাংশনগুলির মতো?
আরবিটি

5
এটি সম্পর্কে জোন স্কিকেট এবং স্কট হ্যানসেলম্যান দ্বারা 2016 এর উপর দরকারী কথোপকথন youtu.be/H2KkiRbDZyc?t=3302
ড্যানিয়েল বি

@ আরবিটি: আমি মনে করি এটি অন্যরকম। এটি পুনরাবৃত্ত কলগুলির সংখ্যা বোঝায়। টেইল কলগুলি কলগুলির সম্বন্ধে যা লেজের অবস্থানে উপস্থিত হয়, অর্থাৎ শেষ কাজটি কোনও ফাংশন করে তাই এটি সরাসরি কলি থেকে ফলাফলটি ফিরিয়ে দেয়।
জেডি

উত্তর:


84

সংকলন পর্বে খুব বেশি সময় ব্যয় না করা (এইভাবে স্বল্পকালীন অ্যাপ্লিকেশনগুলি যথেষ্ট গতি কমিয়ে দেওয়া) এর মধ্যে জেআইটি সংকলন একটি জটিল ব্যালেন্সিং আইন, বনাম। দীর্ঘমেয়াদে অ্যাপ্লিকেশনটিকে একটি মানসম্মত সাময়িক সংকলনের সাথে প্রতিযোগিতামূলক রাখার জন্য পর্যাপ্ত বিশ্লেষণ না করা ।

মজার বিষয় হল এনজিএন সংকলন পদক্ষেপগুলি তাদের অপ্টিমাইজেশনে আরও আক্রমণাত্মক হওয়ার লক্ষ্যবস্তু নয়। আমার সন্দেহ হয় কারণ এটি কেবল কোনও বাগ থাকতে চায় না যেখানে আচরণটি নির্ভর করে যে মেশিন কোডের জন্য জেআইটি বা এনজেন দায়বদ্ধ ছিল কিনা তার উপর।

CLR নিজেই সমর্থন লেজ কল অপ্টিমাইজেশান না, কিন্তু ভাষা-নির্দিষ্ট কম্পাইলার জানতে হবে কিভাবে প্রাসঙ্গিক জেনারেট করতে opcode এবং জে আই টি JIT এটা সম্মান করতে ইচ্ছুক হতে হবে। এফ # এর এফএসসি প্রাসঙ্গিক ওপকোড তৈরি করবে (যদিও একটি সাধারণ পুনরাবৃত্তির জন্য এটি কেবল পুরো জিনিসটিকে whileসরাসরি লুপে রূপান্তর করতে পারে )। সি # এর সিসিএস করে না।

কিছু বিবরণের জন্য এই ব্লগ পোস্টটি দেখুন (সাম্প্রতিক জেআইটি পরিবর্তনের পরিবর্তে এখন সম্ভবত পুরানো)। নোট করুন যে সিএলআর 4.0 এর জন্য x86, x64 এবং ia64 পরিবর্তন করে এটি সম্মান করবে


2
এই পোস্টটিও দেখুন: social.msdn.microsoft.com/forums/en-US/netfxtoolsdev/thread/… যার মধ্যে আমি জানতে পারি যে লেজ একটি নিয়মিত কলের চেয়ে ধীর is EEP!
প্লিন্থ

77

এই মাইক্রোসফ্ট কানেক্টের প্রতিক্রিয়া জমা দেওয়ার ক্ষেত্রে আপনার প্রশ্নের উত্তর দেওয়া উচিত। এটিতে মাইক্রোসফ্টের একটি অফিশিয়াল প্রতিক্রিয়া রয়েছে, সুতরাং আমি এটি অনুসরণ করার প্রস্তাব দিই।

পরামর্শের জন্য ধন্যবাদ. আমরা সি # সংকলকটির বিকাশের বেশ কয়েকটি পয়েন্টে টেইল কল নির্দেশনা নির্গত করার বিষয়টি বিবেচনা করেছি। যাইহোক, কিছু সূক্ষ্ম সমস্যা রয়েছে যা আমাদের এ পর্যন্ত এড়িয়ে চলতে বাধ্য করেছে: 1) সিএলআরতে টেইল নির্দেশটি ব্যবহার করার ক্ষেত্রে আসলে একটি অ-তুচ্ছ ওভারহেড ব্যয় হয় (লেজ আহ্বান অবশেষে পরিণত হওয়ার সাথে সাথে এটি কেবল লাফের নির্দেশ নয়) অনেক কম কঠোর পরিবেশ যেমন ফাংশনাল ল্যাঙ্গুয়েজ রানটাইম এনভায়রনমেন্টগুলিতে যেখানে টেল কলগুলি প্রচুরভাবে অনুকূলিত করা হয়)। 2) কয়েকটি আসল সি # পদ্ধতি রয়েছে যেখানে লেজ কল নির্ধারণ আইনী হবে (অন্যান্য ভাষাগুলি কোডিং নিদর্শনগুলিতে উত্সাহ দেয় যা বেশি লেজ পুনরাবৃত্তি করে, এবং লেজ কল অপ্টিমাইজেশনের উপর প্রচুরভাবে নির্ভর করে এমন অনেকেই লেজ পুনরাবৃত্তির পরিমাণ বাড়ানোর জন্য বিশ্বব্যাপী পুনর্লিখন (যেমন কন্টিনিয়েশন পাসিং ট্রান্সফরমেশনস) করেন। ৩) আংশিকভাবে ২ এর কারণে), যে ক্ষেত্রে সি # পদ্ধতিগুলি গভীর পুনরাবৃত্তির কারণে ওভারফ্লো স্ট্যাক করে যা সফল হওয়া উচিত ছিল তা বিরল rare

যা যা বলেছিল, আমরা এটি অবিরত রেখেছি এবং ভবিষ্যতে সংকলকটির প্রকাশে কিছু নিদর্শন পাওয়া যেতে পারে যেখানে এটি নির্গত হওয়ার অর্থ হয় t

উপায় দ্বারা, যেমন নির্দিষ্ট করা হয়েছে, এটা লক্ষণীয় যে, লেজ পুনরাবৃত্তির মূল্য হয় x64 উপর অপ্টিমাইজ করা।


3
আপনিও এটি সহায়ক খুঁজে পেতে পারেন: weblogs.asp.net/podwysocki/archive/2008/07/07/…
নলডোরিন

কোনও সমস্যা নেই, আপনি এটি সহায়ক বলে খুশী।
নলডোরিন

17
এটি উদ্ধৃত করার জন্য আপনাকে ধন্যবাদ, কারণ এটি এখন একটি 404!
রোমান স্টারকভ

3
লিঙ্কটি এখন ঠিক করা হয়েছে।
luksan

15

সি # টেল-কল পুনরাবৃত্তির জন্য অনুকূল করে না কারণ এফ # এর জন্যই!

সি # সংকলকটিকে টেল-কল অপ্টিমাইজেশান সম্পাদন থেকে বিরত করার শর্তগুলির কিছু গভীরতার জন্য, এই নিবন্ধটি দেখুন: জেআইটি সিএলআর টেল-কল শর্তাদি

সি # এবং এফ # এর মধ্যে আন্তঃক্রিয়াশীলতা

সি # এবং এফ # আন্তঃব্যবস্থাপনা খুব ভাল, এবং .NET কমন ল্যাঙ্গুয়েজ রানটাইম (সিএলআর) এই আন্তঃব্যবহার্যতার কথা মাথায় রেখে তৈরি করা হয়েছে, প্রতিটি ভাষা তার উদ্দেশ্য এবং উদ্দেশ্যগুলির সাথে সুনির্দিষ্টভাবে অনুকূলিতকরণের সাথে ডিজাইন করা হয়েছে। একটি উদাহরণ যা দেখায় যে সি # কোড থেকে এফ # কোড কল করা কতটা সহজ, সি # কোড থেকে এফ # কোড কল করা দেখুন ; এফ # কোড থেকে সি # ফাংশন কল করার উদাহরণের জন্য, এফ # থেকে সি # ফাংশন কল করা দেখুন ।

প্রতিনিধি আন্তঃব্যবহারযোগ্যতার জন্য, এই নিবন্ধটি দেখুন: F #, C # এবং ভিজ্যুয়াল বেসিকের মধ্যে আন্তঃক্ষমতা প্রেরণ করুন ।

সি # এবং এফ # এর মধ্যে তাত্ত্বিক এবং ব্যবহারিক পার্থক্য

এখানে একটি নিবন্ধ যা কিছু পার্থক্যকে কভার করে এবং সি # এবং এফ # এর মধ্যে টেল-কল পুনরাবৃত্তির নকশা পার্থক্য ব্যাখ্যা করে: সি # এবং এফ # তে টেল-কল অপকোড তৈরি করছে

এখানে সি #, এফ #, এবং সি ++ \ সিএলআই-এর কয়েকটি উদাহরণ সহ একটি নিবন্ধ রয়েছে: সি #, এফ #, এবং সি ++ \ সিএলআই এ টেল পুনরাবৃত্তি

মূল তাত্ত্বিক পার্থক্যটি হ'ল সি # লুপের সাথে ডিজাইন করা হয়েছে যেখানে এফ # লাম্বদা ক্যালকুলাসের নীতি অনুসারে ডিজাইন করা হয়েছে। ল্যাম্বদা ক্যালকুলাসের নীতিগুলি সম্পর্কে একটি খুব ভাল বইয়ের জন্য, এই নিখরচায় বইটি দেখুন: অ্যাবেলসন, সুসমান এবং সুসমানের লেখা কম্পিউটার প্রোগ্রামগুলির কাঠামো এবং ব্যাখ্যার ব্যবস্থা

এফ # তে টেল কল সম্পর্কিত একটি খুব ভাল সূচনামূলক নিবন্ধের জন্য, এই নিবন্ধটি দেখুন: এফ # তে টেল কলগুলির বিশদ ভূমিকা । অবশেষে, এখানে একটি নিবন্ধ রয়েছে যা অ-লেজ পুনরাবৃত্তি এবং লেজ-কল পুনরাবৃত্তি (এফ # তে) এর মধ্যে পার্থক্যকে অন্তর্ভুক্ত করে: টেল-পুনরাবৃত্তি বনাম এফ শার্পে অ-লেজ পুনরাবৃত্তি


8

আমাকে সম্প্রতি বলা হয়েছিল যে #৪ বিটের জন্য সি # সংকলক লেজ পুনরাবৃত্তিকে অনুকূল করে তোলে।

সি # এটি প্রয়োগ করে। এটি সর্বদা প্রয়োগ না হওয়ার কারণ, লেজ পুনরাবৃত্তি প্রয়োগ করতে ব্যবহৃত নিয়মগুলি অত্যন্ত কঠোর very


8
এক্স 64 জিটারটি এটি করে, তবে সি #
সংকলকটি এটি

তথ্যের জন্য ধন্যবাদ. আমি সাদা ভাবনার পরে আলাদা হয়েছি previously
আলেকজান্দ্রে ব্রাইসোবাইস

3
কেবল এই দুটি মন্তব্য স্পষ্ট করার জন্য, সি # কখনও সিআইএল 'লেজ' অপকোডটি প্রকাশ করে না, এবং আমি বিশ্বাস করি যে এটি 2017 সালে এখনও সত্য However তবে, সমস্ত ভাষার ক্ষেত্রে, অপকডটি সর্বদা কেবল এই অর্থেই পরামর্শদাতা যে সম্পর্কিত জিটটারগুলি (x86, x64) ) যদি জড়িত শর্তগুলি পূরণ না করা হয় তবে চুপচাপ এটিকে উপেক্ষা করা হবে (ভাল, সম্ভাব্য স্ট্যাক ওভারফ্লো ছাড়া কোনও ত্রুটি নেই )। এটি আপনাকে 'রেট' দিয়ে 'লেজ' অনুসরণ করতে বাধ্য করার কারণ ব্যাখ্যা করে - এটি এই ক্ষেত্রে। এদিকে, সিআইএল-তে কোনও 'লেজ' উপসর্গ নেই, আবার উপযুক্ত হিসাবে বিবেচিত, এবং নেট ভাষা নির্বিশেষে জিটরগুলিও অপ্টিমাইজেশন প্রয়োগ করতে মুক্ত।
গ্লেন স্লেডেন

3

আপনি সি # (বা জাভা) এর লেজ-পুনরাবৃত্তির জন্য ট্রাম্পোলিন কৌশলটি ব্যবহার করতে পারেন । যাইহোক, আরও ভাল সমাধান (যদি আপনি কেবল স্ট্যাকের ব্যবহার সম্পর্কে যত্নশীল হন) হ'ল এই ছোট সহায়ক সহায়ক পদ্ধতিটি একই পুনরাবৃত্ত ফাংশনের অংশগুলি মোড়ানো এবং ফাংশনটি পঠনযোগ্য রাখার সময় পুনরাবৃত্ত করে তোলে।


ট্রাম্পোলাইনগুলি আক্রমণাত্মক (তারা কলিং কনভেনশনে একটি বিশ্বব্যাপী পরিবর্তন), যথাযথ লেজ কল নির্মূলের চেয়ে 10x ডলার ধীরে ধীরে এবং তারা সমস্ত স্ট্যাকের ট্রেস তথ্যকে ডিবাগ করা এবং প্রোফাইল কোডকে আরও শক্ত করে তোলে
জেডি

1

উল্লিখিত অন্যান্য উত্তর হিসাবে, সিএলআর লেজ কল অপ্টিমাইজেশান সমর্থন করে এবং মনে হয় এটি historতিহাসিকভাবে প্রগতিশীল উন্নতির অধীনে ছিল। তবে সি # তে এটি সমর্থনProposal করার সাথে সি # প্রোগ্রামিং ল্যাঙ্গুয়েজ সাপোর্ট টেইল রিকার্সন # 2544 ডিজাইনের জন্য গিট সংগ্রহস্থলটিতে একটি উন্মুক্ত সমস্যা রয়েছে ।

আপনি কিছু দরকারী বিশদ এবং তথ্য সেখানে পেতে পারেন। উদাহরণস্বরূপ @ জাইক্রেল উল্লেখ করেছেন

আমি যা জানি তা দিতে দিন।

কখনও কখনও টেলকল একটি পারফরম্যান্স উইন-উইন। এটি সিপিইউ বাঁচাতে পারে। জেএমপি কল / রিটের চেয়ে কম সস্তা এটি স্ট্যাক সংরক্ষণ করতে পারে। কম স্ট্যাকের ছোঁয়া আরও ভাল লোকেশন তৈরি করে।

কখনও কখনও টেল্কল একটি পারফরম্যান্স হ্রাস, স্ট্যাক জয়। সিএলআরের একটি জটিল প্রক্রিয়া রয়েছে যার মধ্যে কলারের চেয়ে বেশি পরামিতি কলারের কাছে পৌঁছানো। আমি পরামিতিগুলির জন্য বিশেষত আরও স্ট্যাক স্পেস বলতে চাইছি। এটি ধীর। তবে এটি স্ট্যাক সংরক্ষণ করে। এটি কেবল লেজ দিয়ে এটি করবে। উপসর্গ।

যদি কলার প্যারামিটারগুলি কলি প্যারামিটারগুলির তুলনায় স্ট্যাক-বড় হয় তবে এটি সাধারণত একটি খুব সহজ উইন-উইন ট্রান্সফর্ম। প্যারামিটার-অবস্থানের ব্যবস্থাপনার থেকে পূর্ণসংখ্যার / ফ্লোটে পরিবর্তন করা এবং সুনির্দিষ্ট স্ট্যাকম্যাপগুলি তৈরি করা এবং এর মতো কারণ থাকতে পারে।

স্থির / ছোট স্ট্যাক সহ নির্বিচারে বৃহত ডেটা প্রক্রিয়া করতে সক্ষম হওয়ার উদ্দেশ্যে, এখন অন্য একটি কোণ রয়েছে, যেটি অ্যালগরিদমগুলি টেলকেল নির্মূলকরণের দাবি করে। এটি পারফরম্যান্স সম্পর্কে নয়, তবে মোটেও চালানোর ক্ষমতা সম্পর্কে।

আমি আরও উল্লেখ করি (অতিরিক্ত তথ্য হিসাবে), যখন আমরা System.Linq.Expressionsনেমস্পেসে এক্সপ্রেশন ক্লাস ব্যবহার করে একটি সংকলিত লাম্বদা তৈরি করি, তখন 'টেলক্যাল' নামে একটি যুক্তি রয়েছে যা তার মন্তব্যে ব্যাখ্যা করা হয়েছে এটি হ'ল

একটি বিল যা ইঙ্গিত করে যে টেল কল অপ্টিমাইজেশন তৈরি করা এক্সপ্রেশনটি সংকলনের সময় প্রয়োগ করা হবে।

আমি এটি এখনও চেষ্টা করা হয়নি, এবং আমি নিশ্চিত না যে এটি আপনার প্রশ্নের সাথে সম্পর্কিত কীভাবে সহায়তা করতে পারে, তবে সম্ভবত কেউ এটি চেষ্টা করতে পারে এবং কিছু পরিস্থিতিতে কার্যকর হতে পারে:


var myFuncExpression = System.Linq.Expressions.Expression.Lambda<Func<  >>(body:  , tailCall: true, parameters:  );

var myFunc =  myFuncExpression.Compile();
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.