আধুনিক সংকলকগুলিতে এখনও ফাংশন কল ব্যয়গুলি কীভাবে গুরুত্বপূর্ণ?


95

আমি একজন ধার্মিক ব্যক্তি এবং পাপ না করার চেষ্টা করি। এই কারণেই ক্লিন কোড বাইবেলের নির্দেশিত বেশ কয়েকটি আদেশের সাথে আমি মেনে চলার জন্য ছোট (তার চেয়ে ছোট রবার্ট সি মার্টিনকে রেকর্ড করতে) ফাংশন লিখি । তবে কিছু জিনিস পরীক্ষা করার সময়, আমি এই পোস্টে অবতরণ করেছি , যার নীচে আমি এই মন্তব্যটি পড়েছি:

মনে রাখবেন যে কোনও পদ্ধতির কলটির দাম ভাষার উপর নির্ভর করে উল্লেখযোগ্য হতে পারে। পঠনযোগ্য কোড এবং পারফরম্যান্ট কোড লেখার মধ্যে প্রায় সবসময়ই একটি বাণিজ্য থাকে off

কোন অবস্থার অধীনে আজকাল এই উদ্ধৃত বিবৃতিটি কার্যকর আধুনিক সংকলকগুলির সমৃদ্ধ শিল্পকে দেওয়া বৈধ?

এটাই আমার একমাত্র প্রশ্ন। এবং আমার দীর্ঘ বা ছোট ফাংশন লিখতে হবে কিনা তা নিয়ে নয়। আমি কেবল হাইলাইট করেছি যে আপনার মতামত আমার দৃষ্টিভঙ্গি পরিবর্তনে অবদান রাখতে পারে এবং আমাকে নিন্দাকারীদের প্রলোভনের বিরুদ্ধে প্রতিরোধ করতে অক্ষম করে ।


11
পঠনযোগ্য এবং রক্ষণাবেক্ষণযোগ্য কোড লিখুন। কেবল যখন আপনি স্ট্যাক ওভারফ্লোতে কোনও সমস্যার মুখোমুখি হন তখনই আপনি আপনার এসপ্রোচটি পুনরায় চিন্তা করতে পারেন
ফ্যাবিও

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

6
ব্যক্তিগত অভিজ্ঞতা থেকে কথা বলি, আমি একটি স্বতন্ত্র ভাষায় কোড লিখি যা সামর্থ্যের দিক থেকে মোটামুটি আধুনিক, তবে ফাংশন কলগুলি হাস্যকরভাবে ব্যয়বহুল, যেখানে লুপগুলির জন্য এমনকি সাধারণের গতির জন্য অপ্টিমাইজ করাতে হবে: for(Integer index = 0, size = someList.size(); index < size; index++)কেবলমাত্র পরিবর্তে for(Integer index = 0; index < someList.size(); index++)। আপনার সংকলকটি গত কয়েক বছরে তৈরি করা হয়েছিল বলে প্রয়োজনীয়ভাবে বোঝানো হয়নি যে আপনি প্রোফাইলিং পূর্ববর্তী করতে পারেন।
ফায়ারফক্স

5
@ ফাইরফক্স যে লুটের মাধ্যমে প্রতিবার কল করার পরিবর্তে লুপের বাইরে কিছু তালিকাভুক্ত (সাইজ) এর মূল্য পেয়েছে তা উপলব্ধি করে। এটি বিশেষত সত্য যদি সংশ্লেষনের সমস্যা হওয়ার কোনও সম্ভাবনা থাকে যেখানে পাঠক এবং লেখকগণ পুনরাবৃত্তির সময় সংঘর্ষের চেষ্টা করতে পারে, সেক্ষেত্রে আপনি পুনরাবৃত্তির সময় কোনও পরিবর্তনগুলির বিরুদ্ধে তালিকাটি সুরক্ষিত করতেও চাইবেন।
ক্রেগ

8
খুব বেশি ছোট ছোট ফাংশন নেওয়ার বিষয়ে সতর্ক থাকুন, এটি কোডটি ঠিক ততটাই দক্ষতার সাথে অবিচ্ছিন্ন করতে পারে যেমন কোনও একক মেগা-ফাংশন করে। আপনি যদি আমাকে বিশ্বাস না করেন তবে ioccc.org বিজয়ীদের মধ্যে কিছু পরীক্ষা করে দেখুন : কিছু কোড সবকিছুকে একটি একক করে main()তোলে, অন্যরা সমস্ত কিছুকে 50 টি ক্ষুদ্র ফাংশনে বিভক্ত করে এবং সবগুলি একেবারে অপঠনযোগ্য। কৌশলটি যথারীতি যথাযথ ভারসাম্য বজায় রাখা

উত্তর:


148

এটি আপনার ডোমেনের উপর নির্ভর করে।

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

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

এবং সর্বশেষে, এখানে পারফরম্যান্সের সুবর্ণ নিয়ম রয়েছে: সর্বদা প্রোফাইল প্রথম। অনুমানের উপর ভিত্তি করে "অনুকূলিত" কোডটি লিখবেন না। আপনি যদি অকার্যকর হন তবে উভয় ক্ষেত্রেই লিখুন এবং দেখুন কোনটি ভাল।


13
এবং উদাহরণস্বরূপ হটস্পট সংকলক অনুমানমূলক ইনলাইনিং সম্পাদন করে , যা সম্ভব না হলেও এমনকি কিছুটা অর্থে ইনলাইন করা হয় ।
জার্গ ডব্লু মিট্টাগ

49
আসলে, একটি ওয়েব অ্যাপ্লিকেশনটিতে, পুরো কোডটি সম্ভবত ডিবি অ্যাক্সেস এবং নেটওয়ার্ক ট্র্যাফিকের ক্ষেত্রে তুচ্ছ ...
AnoE

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

2
@ মেহরদাদ এমনকি এই ক্ষেত্রে কোডটিতে অনুকূলিত হওয়ার জন্য আরও কিছু প্রাসঙ্গিক না থাকলে আমি অবাক হব। কোডটি প্রোফাইল করার সময় আমি জিনিসগুলি ফাংশনগুলির চেয়ে বেশি ভারী দেখতে পাই এবং এটিই অপ্টিমাইজেশনের সন্ধানের জন্য প্রাসঙ্গিক। কিছু ডেভস এক বা দুটি অব্যবহৃত এলওসি-র জন্য উন্মাদ হয়ে যায় তবে আপনি যখন এসডাব্লু প্রোফাইল করেন তখন আপনি বুঝতে পারবেন যে নকশাগুলি এটির চেয়েও কম গুরুত্বপূর্ণ, কোডের সবচেয়ে বড় অংশের জন্য। যখন আপনি বাধাটি খুঁজে পান আপনি এটি অনুকূলকরণের চেষ্টা করতে পারেন এবং কলগুলি ওভারহেড এড়াতে বড় ফাংশনগুলি লেখার মতো নিম্ন-স্তরের স্বেচ্ছাচারিতা অপ্টিমাইজেশানের চেয়ে এর বেশি প্রভাব পড়বে।
টিম

8
ভাল উত্তর! আপনার শেষ পয়েন্টটি প্রথম হওয়া উচিত: কোথায় অনুকূলিত করার সিদ্ধান্ত নেওয়ার আগে সর্বদা প্রোফাইল
সিজে ডেনিস

56

ফাংশন কল ওভারহেড সম্পূর্ণরূপে ভাষার উপর নির্ভর করে এবং আপনি কোন স্তরে অপ্টিমাইজ করছেন।

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

উচ্চ স্তরে, পার্ল, পাইথন, রুবির মতো ভাষাগুলি ফাংশন কলটিতে প্রচুর বুককিপিং করে, সেগুলি তুলনামূলকভাবে ব্যয়বহুল করে তোলে। এটি মেটা-প্রোগ্রামিং দ্বারা আরও খারাপ করা হয়েছে। আমি একবার খুব উত্তপ্ত লুপ থেকে ফাংশন কলগুলি উত্তোলন করে পাইথন সফ্টওয়্যার 3x একবার বাড়িয়েছি। কর্মক্ষমতা-সমালোচনামূলক কোডে, ইনলাইনিং সহায়ক ফাংশনগুলি লক্ষণীয় প্রভাব ফেলতে পারে।

তবে সফ্টওয়্যারটির বিস্তৃত অংশটি এতটা পারফরম্যান্স-সমালোচক নয় যে আপনি ফাংশন কল ওভারহেডে লক্ষ্য করতে সক্ষম হবেন। যাই হোক না কেন, পরিষ্কার, সহজ কোড লেখার ব্যয় হয়:

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

  • যদি আপনার কোড পারফরম্যান্স-সমালোচনামূলক হয় তবে সাধারণ কোডটি কোডটি বোঝা আরও সহজ করে তোলে এবং অপ্টিমাইজেশনের জন্য স্পট সুযোগগুলি। সবচেয়ে বড় জয় সাধারণত ইনলাইনিং ফাংশনগুলির মতো মাইক্রো-অপটিমাইজেশন থেকে আসে না, তবে অ্যালগরিদমিক উন্নতি থেকে আসে। বা ভিন্নভাবে বানানো: একই জিনিসটি দ্রুত করবেন না। কম করার উপায় খুঁজে নিন।

নোট করুন যে "সিম্পল কোড" এর অর্থ "হাজার হাজার ক্ষুদ্র ক্রিয়াকলাপগুলিতে সংযুক্ত" নয়। প্রতিটি ফাংশন কিছুটা জ্ঞানীয় ওভারহেডেরও পরিচয় করিয়ে দেয় - আরও বিমূর্ত কোড সম্পর্কে যুক্তিযুক্ত করা আরও কঠিন । কিছু সময়ে, এই ক্ষুদ্র ফাংশনগুলি এত কম করতে পারে যে এগুলি ব্যবহার না করা আপনার কোডটি সহজতর করবে।


16
সত্যিই একটি স্মার্ট ডিবিএ আমাকে একবার বলেছিল "এটির ব্যথা না হওয়া পর্যন্ত স্বাভাবিক করুন, যতক্ষণ না এটি হয় ততক্ষণ পর্যন্ত অস্বীকৃতি করুন।" আমার কাছে মনে হয় এটি "পুনরুদ্ধার করা যেতে পারে পদ্ধতিগুলি উত্তোলন না করা পর্যন্ত এটি এক্সট্রাক্ট করুন, তারপরে এটি ইনलाइन না হওয়া পর্যন্ত ইনলাইন করুন।"
রাবারডাক

1
জ্ঞানীয় ওভারহেড ছাড়াও, ডিবাগার তথ্যে প্রতীকী ওভারহেড থাকে এবং সাধারণত চূড়ান্ত বাইনারিগুলিতে ওভারহেড অনিবার্য থাকে।
ফ্র্যাঙ্ক হিলিমান

স্মার্ট সংকলকগুলির বিষয়ে - তারা এটি করতে পারে, কেবল সর্বদা নয়। উদাহরণস্বরূপ jvm অস্বাভাবিক পাথ বা ইনলাইন পলিমারফিক ফাংশনের জন্য খুব সস্তার / ফ্রি ট্র্যাপের সাথে রানটাইম প্রোফাইলের উপর ভিত্তি করে জিনিসগুলিকে ইনলাইন করতে পারে যার জন্য প্রদত্ত পদ্ধতি / ইন্টারফেসের কেবলমাত্র একটি প্রয়োগ রয়েছে এবং তারপরে যখন নতুন সাবক্লাসটি গতিশীলভাবে লোড হয় তখন কলটি সঠিকভাবে পলিমারফিককে ডুপিমাইজ করতে পারে রানটাইম। তবে হ্যাঁ, এমন অনেকগুলি ভাষা রয়েছে যেখানে এই জাতীয় জিনিসগুলি সম্ভব হয় না এবং জেভিএম-তে এমনকি অনেকগুলি ক্ষেত্রেও কার্যকর হয় না যখন সাধারণ ক্ষেত্রে এটি কার্যকর হয় না।
আরতুর বিসিয়াদভস্কি

19

পারফরম্যান্সের জন্য টিউনিং কোড সম্পর্কে প্রায় সমস্ত অ্যাডেজ আমদাহলের আইনের বিশেষ বিষয় । আমদাহলের আইনের সংক্ষিপ্ত, হাস্যকর বক্তব্য

যদি আপনার প্রোগ্রামের একটি অংশটি রানটাইমের 5% নেয় এবং আপনি সেই অংশটিকে অনুকূলিত করেন যাতে এটি এখন রানটাইমের শূন্য শতাংশ নেয় তবে পুরো প্রোগ্রামটি কেবলমাত্র 5% দ্রুততর হবে।

(রানটাইমের শূন্য শতাংশে জিনিসকে অপ্টিমাইজ করা সম্পূর্ণভাবে সম্ভব: আপনি যখন কোনও বৃহত, জটিল প্রোগ্রামকে অনুকূলিতকরণ করতে বসেন তখন আপনি সম্ভবত খুঁজে পেতে পারেন যে এটি কমপক্ষে তার রানটাইমের কিছুটা স্টাফের জন্য ব্যয় করছে যা একেবারেই করার দরকার নেই) ।)

এ কারণেই লোকেরা সাধারণত ফাংশন কলের ব্যয় নিয়ে উদ্বিগ্ন হওয়ার কথা বলেন না: তারা যতই ব্যয়বহুল, সাধারণভাবে পুরো প্রোগ্রামটি কেবল তার ওভারহেডের রানটাইমটির একটি ক্ষুদ্র ক্ষুদ্র অংশ ব্যয় করে, তাই তাদের গতি বাড়ানো খুব বেশি সহায়তা করে না doesn't ।

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

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

  • যদি কোনও ফাংশনের প্রতি-অনুরোধ রানটাইমটি মিলিসেকেন্ডের চেয়ে কম হয় তবে সেই ফাংশনটিকে কয়েক হাজার বার বলা হয়, এটি সম্ভবত ইনলাইন করা উচিত।

  • যদি প্রোগ্রামটির একটি প্রোফাইল কয়েক হাজার ফাংশন দেখায় এবং এগুলির কোনওটি রানটাইমের চেয়ে 0.1% বা তার বেশি গ্রহণ করে না , তবে ফাংশন-কল ওভারহেড সম্ভবত সামগ্রিকভাবে গুরুত্বপূর্ণ significant

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


7
নেস্টেড লুপগুলি গভীরভাবে সম্পন্ন ব্যয়বহুল জিনিসগুলি থেকে সাবধান থাকুন। আমি একটি ফাংশন অনুকূলিত করেছি এবং কোড পেয়েছি যা 10x হিসাবে দ্রুত চালায় runs প্রোফাইলার অপরাধীর দিকে ইঙ্গিত করার পরে এটি হয়েছিল। (এটা বহুবার, লুপ মধ্যে O থেকে (ঢ ^ 3) একটি ছোট N O (ঢ ^ 6) ডাক পেয়েছিলেন।)
লরেন Pechtel

"দুর্ভাগ্যক্রমে, এর একমাত্র প্রতিকার হ'ল কিছু স্তর থেকে মুক্তি পাওয়া, যা প্রায়শই খুব কঠিন।" - এটি আপনার ভাষা সংকলক এবং / অথবা ভার্চুয়াল মেশিন প্রযুক্তির উপর খুব নির্ভর করে। আপনি যদি কোডটি সংযোজককে সহজেই ইনলাইন করা সহজ করতে কোড পরিবর্তন করতে পারেন (যেমন finalজাভাতে প্রযোজ্য ক্লাস এবং পদ্ধতিগুলি ব্যবহার করে , বা virtualসি # বা সি ++ তে নন- পদ্ধতিগুলি ব্যবহার করে) তবে সংকলক / রানটাইম দ্বারা ইন্ডিয়ারেশনটি মুছে ফেলা যায় এবং আপনি ' বিশাল পুনর্গঠন ছাড়াই একটি লাভ দেখতে পাবেন। @ জর্জিডব্লিউমিত্যাগ যেমন উপরে উল্লেখ করেছেন যে, জেভিএম এমন ক্ষেত্রেও ইনলাইন করতে পারে যেখানে অপ্টিমাইজেশনটি প্রমাণিত হয় না ...
জুলাই

... বৈধ, সুতরাং এটি ভাল হতে পারে যে যাইহোক লেয়ারিং সত্ত্বেও এটি আপনার কোডটিতে এটি করছে।
জুলাই

@Jules যদিও এটা সত্যি যে জে আই টি JIT কম্পাইলার করতে ফটকামূলক অপ্টিমাইজেশান কার্য সম্পাদন, তার অর্থ এই নয় যে এই ধরনের অপ্টিমাইজেশন হয় অবিশেষে প্রয়োগ করা হয়েছে। বিশেষত জাভা সম্পর্কিত, আমার অভিজ্ঞতা হ'ল বিকাশকারী সংস্কৃতি স্তরগুলির শীর্ষে স্তূপিত স্তরগুলিকে অত্যন্ত গভীর কল স্ট্যাকের দিকে নিয়ে যায়। উপাখ্যান্তভাবে, এটি অনেক জাভা অ্যাপ্লিকেশনগুলির অলস, ফুলে যাওয়া অনুভূতিতে অবদান রাখে। স্তরগুলি টেকনিক্যালি ইনলাইনযোগ্য কিনা তা নির্বিশেষে এ জাতীয় উচ্চ স্তরযুক্ত আর্কিটেকচার জেআইটি রানটাইমের বিরুদ্ধে কাজ করে। জেআইটি কোনও ম্যাজিক বুলেট নয় যা কাঠামোগত সমস্যাগুলি স্বয়ংক্রিয়ভাবে ঠিক করতে পারে।
আমন

@amon "লাসাগনা কোড" এর সাথে আমার অভিজ্ঞতাটি অনেক বড় সি ++ অ্যাপ্লিকেশন থেকে আসে 1990 এর দশকে প্রচুর কোডের সাথে ডেট হয়, যখন গভীরভাবে নেস্টেড অবজেক্ট হায়ারারচি এবং সিওএম ফ্যাশন ছিল। সি ++ সংকলকগণ এই জাতীয় প্রোগ্রামগুলিতে বিমূর্ততা দন্ডটি কাটাতে যথেষ্ট বীরত্বপূর্ণ প্রচেষ্টায় যান এবং এখনও আপনি তাদেরকে পরোক্ষ-শাখা পাইপলাইন স্টলগুলিতে প্রাচীর-ঘড়ির রানটাইমের একটি উল্লেখযোগ্য অংশ ব্যয় করতে দেখতে পাবেন (এবং আই-ক্যাশে মিস করার ক্ষেত্রে আরও একটি উল্লেখযোগ্য অংশ) ।
zwol

17

আমি এই উদ্ধৃতিটিকে চ্যালেঞ্জ জানাব:

পঠনযোগ্য কোড এবং পারফরম্যান্ট কোড লেখার মধ্যে প্রায় সবসময়ই একটি বাণিজ্য থাকে off

এটি একটি সত্যই বিভ্রান্তিমূলক বিবৃতি এবং সম্ভাব্য বিপজ্জনক মনোভাব। কিছু নির্দিষ্ট ক্ষেত্রে রয়েছে যেখানে আপনাকে ট্রেড অফ করতে হবে, তবে সাধারণভাবে দুটি কারণই স্বাধীন।

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

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

(পাইথনের মতো কিছু গতিময় ভাষার একটি উল্লেখযোগ্য পদ্ধতি-কল ওভারহেড থাকে But তবে যদি পারফরম্যান্স কোনও সমস্যা হয়ে যায় তবে সম্ভবত আপনাকে প্রথমে পাইথন ব্যবহার করা উচিত নয়))

পঠনযোগ্য কোডের জন্য বেশিরভাগ নীতি - ধারাবাহিক ফর্ম্যাটিং, অর্থবহ শনাক্তকারী নাম, উপযুক্ত এবং সহায়ক মন্তব্য এবং এর ফলে পারফরম্যান্সের কোনও প্রভাব নেই। এবং কিছু - স্ট্রিংয়ের পরিবর্তে এনাম ব্যবহার করার মতো - এর পারফরম্যান্স সুবিধাও রয়েছে।


5

ফাংশন কল ওভারহেড বেশিরভাগ ক্ষেত্রে গুরুত্বহীন।

তবে ইনলাইনিং কোড থেকে বড় লাভ ইনলাইন করার পরে নতুন কোডটিকে অনুকূল করে তুলছে

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

ভার্চুয়াল ফাংশন এবং ফাংশন পয়েন্টারগুলি আকর্ষণীয় না হওয়ার এটি একটি বড় কারণ হ'ল প্রকৃত ফাংশন পয়েন্টারটি কল সাইটটিতে সমস্তভাবে অবিচ্ছিন্নভাবে ফোল্ড করা না থাকলে আপনি এগুলি একেবারে ইনলাইন করতে পারবেন না।


5

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

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

OTOH, কলগুলি সম্পাদন করার জন্য একটি অ-সুস্পষ্ট ব্যয় রয়েছে: তাদের কেবলমাত্র অস্তিত্ব কল করার আগে এবং পরে সংকলক অনুকূলিতকরণ বাধা দিতে পারে।

যদি সংকলকটি ডাকা ফাংশনটি কী করে (যেমন এটি ভার্চুয়াল / ডায়নামিক প্রেরণ বা ডায়নামিক লাইব্রেরির কোনও ক্রিয়াকলাপ) নিয়ে যুক্তি করতে না পারে তবে অনুমিতভাবে এটি ধরে নিতে হতে পারে যে ফাংশনটির কোনও পার্শ্ব প্রতিক্রিয়া থাকতে পারে - একটি ব্যতিক্রম ছোঁড়া, সংশোধন করা গ্লোবাল অবস্থা বা পয়েন্টারগুলির মাধ্যমে দেখা কোনও স্মৃতি পরিবর্তন করুন। সংকলকটির অস্থায়ী মান সংরক্ষণ করতে হতে পারে স্মৃতি ফিরে পেতে এবং কল করার পরে সেগুলি পুনরায় পড়তে পারে। এটি কলটির চারদিকে নির্দেশাবলী পুনরায় অর্ডার করতে সক্ষম হবে না, সুতরাং এটি লুপগুলি ভেক্টরাইজ করতে বা লুপগুলির বাইরে অপ্রয়োজনীয় গণনা উত্তোলন করতে অক্ষম হতে পারে।

উদাহরণস্বরূপ, যদি আপনি অকারণে প্রতিটি লুপ পুনরাবৃত্তিতে একটি ফাংশন কল করেন:

for(int i=0; i < /* gasp! */ strlen(s); i++) x ^= s[i];

সংকলক জানতে পারে এটি একটি খাঁটি ফাংশন, এবং এটিকে লুপ থেকে সরিয়ে ফেলুন (উদাহরণস্বরূপ ভয়াবহ ক্ষেত্রে এমনকি দুর্ঘটনাযুক্ত ও (এন ^ 2) ও (এন) হিসাবে অ্যালগরিদম স্থির করে):

for(int i=0, end=strlen(s); i < end; i++) x ^= s[i];

এবং তারপরে প্রশস্ত / সিমডি নির্দেশাবলী ব্যবহার করে একবারে 4/8/16 উপাদানগুলি প্রক্রিয়া করতে লুপটি পুনরায় লিখুন।

তবে আপনি যদি লুপটিতে কিছু অস্বচ্ছ কোডটিতে কল যুক্ত করেন, এমনকি যদি কলটি কিছু না করে এবং নিজেই খুব সস্তা সস্তা হয় তবে সংকলকটিকে সবচেয়ে খারাপ ধারণা করতে হবে - যে কলটি একটি বিশ্বব্যাপী ভেরিয়েবল অ্যাক্সেস করবে যা sপরিবর্তনের মতো একই স্মৃতিতে নির্দেশ করে access এর বিষয়বস্তুগুলি (এটি constযদি আপনার ফাংশনে থাকে তবে এটি constঅন্য কোথাও অ-হতে পারে), অপ্টিমাইজেশনটিকে অসম্ভব করে তোলে:

for(int i=0; i < strlen(s); i++) {
    x ^= s[i];
    do_nothing();
}

3

এই পুরানো কাগজটি আপনার প্রশ্নের উত্তর দিতে পারে:

গাই লুইস স্টিল, জুনিয়র .. "'ব্যয়বহুল প্রক্রিয়া কল' মিথ, বা, প্রক্রিয়া কল বাস্তবায়নকে ক্ষতিকারক হিসাবে বিবেচনা করা, বা, ল্যাম্বদা: দ্য আলটিমেট গোটো" নাম প্রকাশ করা। এমআইটি এআই ল্যাব। এআই ল্যাব মেমো এআইএম -443। অক্টোবর 1977।

সারাংশ:

ফোকলোর বলে যে GOTO বিবৃতিগুলি "সস্তা", যখন পদ্ধতি কলগুলি "ব্যয়বহুল"। এই পৌরাণিক কাহিনীটি মূলত দুর্বলভাবে ডিজাইন করা ভাষা বাস্তবায়নের ফলাফল। এই পুরাণের Theতিহাসিক বৃদ্ধি বিবেচনা করা হয়। উভয় তাত্ত্বিক ধারণা এবং একটি বিদ্যমান বাস্তবায়ন নিয়ে আলোচনা করা হয়েছে যা এই রূপকথাকে অবজ্ঞা করে deb এটি দেখানো হয় যে প্রক্রিয়া কলগুলির সীমাহীন ব্যবহার দুর্দান্ত স্টাইলিশ স্বাধীনতার অনুমতি দেয়। বিশেষত, অতিরিক্ত ভেরিয়েবল প্রবর্তন না করে যে কোনও ফ্লোচার্টকে "কাঠামোগত" প্রোগ্রাম হিসাবে লেখা যেতে পারে। GOTO বিবৃতি এবং পদ্ধতি কলের সাথে অসুবিধাটি অ্যাবস্ট্রাক্ট প্রোগ্রামিং ধারণাগুলি এবং কংক্রিট ভাষা গঠনের মধ্যে দ্বন্দ্ব হিসাবে চিহ্নিত করা হয়।


12
আমি একটি কাগজটিতে অত্যন্ত সন্দেহ করি যে পুরানো "ফাংশন কলের দামগুলি এখনও আধুনিক সংকলকগুলিতে গুরুত্বপূর্ণ" কিনা এই প্রশ্নের উত্তর দেবে ।
কোডি গ্রে

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

4
@ অ্যালেক্সভং 1977 সংকলক অপ্টিমাইজেশনের উপর নির্ভর করা পাথরের যুগে পণ্য দামের প্রবণতার উপর নির্ভর করার মতো। সব কিছু খুব বেশি বদলে গেছে। উদাহরণস্বরূপ, একটি সস্তার ক্রিয়াকলাপ হিসাবে গুন মেমরি অ্যাক্সেস দ্বারা প্রতিস্থাপন করা হত। বর্তমানে, এটি একটি বিশাল ফ্যাক্টর দ্বারা আরও ব্যয়বহুল। ভার্চুয়াল পদ্ধতি কলগুলি তাদের তুলনায় তুলনামূলকভাবে অনেক বেশি ব্যয়বহুল (মেমরি অ্যাক্সেস এবং শাখার ভুল ধারণা), তবে প্রায়শই সেগুলি অপটিমাইজ করা যায় এবং ভার্চুয়াল পদ্ধতি কলটি এমনকি ইনলাইন করা যেতে পারে (জাভা সর্বদা এটি করে), তাই ব্যয় হয় ঠিক শূন্য। 1977 সালে এর মতো কিছুই ছিল না
maaartinus

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

2
@ অ্যালেক্সভং সেই কাগজটি অচল করে দেওয়া সিপিইউ পরিবর্তনের বিষয়ে আরও সুনির্দিষ্ট হওয়ার জন্য: 1977 সালে, একটি প্রধান মেমরি অ্যাক্সেস ছিল একক সিপিইউ চক্র। বর্তমানে, L1 (!) ক্যাশে এমনকি একটি সাধারণ অ্যাক্সেস 3 থেকে 4 চক্রের বিলম্ব রয়েছে। এখন, ফাংশন কলগুলি মেমোরি অ্যাক্সেসগুলিতে (স্ট্যাক ফ্রেম তৈরি করা, ফেরতের ঠিকানা সংরক্ষণ করা, স্থানীয় ভেরিয়েবলগুলির জন্য রেজিস্টারগুলি সংরক্ষণ করা) খুব সহজেই চলে আসে, যা সহজেই একক ফাংশন কলের খরচ 20 এবং আরও বেশি চক্রের দিকে চালিত করে। যদি আপনার ফাংশনটি কেবল তার যুক্তিগুলিকে পুনরায় সাজায় এবং কল-থ্রোতে যাওয়ার জন্য সম্ভবত আরও একটি ধ্রুবক যুক্তি যুক্ত করে, তবে এটি প্রায় 100% ওভারহেড।
11:57

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

  • স্ট্যাক-ফ্রেম সম্পর্কিত অপ্টিমাইজেশন রয়েছে যা আপনার উচ্চ ফ্যাক্টর কোডটি ছেড়ে দেওয়ার আগে তদন্ত করা উচিত।

  • বেশিরভাগ সময় যখন আমাকে ধীর প্রোগ্রামের সাথে মোকাবিলা করতে হয়েছিল আমি দেখতে পেলাম অ্যালগরিদমিক পরিবর্তনগুলি ইন-আস্তরণের ফাংশন কলগুলির চেয়ে অনেক বেশি গতি বাড়িয়েছে। উদাহরণস্বরূপ: অন্য ইঞ্জিনিয়ার একটি পার্সারকে পুনরায় redd করে যা মানচিত্রের মানচিত্রের কাঠামো পূরণ করেছে। এর অংশ হিসাবে তিনি একটি মানচিত্র থেকে যুক্তিযুক্তভাবে যুক্ত কোনও ক্যাশেড সূচকটি সরিয়েছেন। এটি একটি দুর্দান্ত কোড দৃust়তা পদক্ষেপ ছিল, তবে এটি সঞ্চিত সূচক ব্যবহার করে ভবিষ্যতে সমস্ত অ্যাক্সেসের জন্য একটি হ্যাশ লুক্কুলিং করার কারণে 100 টি ধীরগতির কারণের কারণে প্রোগ্রামটি অযোগ্য করে তুলেছে। প্রোফাইলিং দেখিয়েছিল যে বেশিরভাগ সময় হ্যাশিংয়ের কাজে ব্যয় হয়েছিল।


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

@ এসএমএলটার্স: আমি মনে করি আপনি "বিশেষত" "আরও" আরও কিছু বা কিছু দিয়ে ভুল করেছেন। অনুলিপি বা রেফারেন্সগুলি পাস করার সিদ্ধান্তটি সি ++ 11 এর আগে ছিল (আমি জানি আপনি এটি জানেন)।
ফ্রেসনেল

@ ফ্রেসনেল: আমি মনে করি এটি ঠিক হয়ে গেছে। আমি যে বিশেষ কেসটির কথা উল্লেখ করছি সেটি হ'ল আপনি যেখানে কলারে অস্থায়ীতা তৈরি করেন, এটিকে একটি যুক্তিতে সরিয়ে দিন এবং তারপরে এটি কলিতে পরিবর্তন করুন। সি ++ ১১ এর আগে এটি সম্ভব ছিল না, কারণ সি ++ 03 কোনও অস্থায়ী রেফারেন্সকে আবদ্ধ করতে পারে না / করতে পারে না
এমসাল্টারস

@ ক্ষুদ্রলোক: তারপরে আমি প্রথমে আপনার মন্তব্যটি পড়ার পরে ভুল বুঝেছি। আমার কাছে মনে হয়েছিল আপনি বোঝাচ্ছেন যে সি ++ 11 এর আগে, মান দ্বারা পাস করা এমন কিছু ছিল না যে কেউ যদি পাস করা মানটি সংশোধন করতে চায়।
ফ্রেস্নেল

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

3

অন্যরা যেমন বলেছে, আপনার প্রোগ্রামটির কর্মক্ষমতা প্রথমে পরিমাপ করা উচিত এবং সম্ভবত অনুশীলনে কোনও পার্থক্য পাবেন না find

তবুও, একটি ধারণাগত স্তর থেকে আমি ভেবেছিলাম যে আমি আপনার প্রশ্নে জড়িত কয়েকটি জিনিস পরিষ্কার করব। প্রথমত, আপনি জিজ্ঞাসা:

আধুনিক সংকলকগুলিতে এখনও ফাংশন কল ব্যয় গুরুত্বপূর্ণ?

"ফাংশন" এবং "সংকলক" কী শব্দগুলি লক্ষ্য করুন। আপনার উদ্ধৃতিটি সূক্ষ্মভাবে পৃথক:

মনে রাখবেন যে কোনও পদ্ধতির কলটির দাম ভাষার উপর নির্ভর করে উল্লেখযোগ্য হতে পারে।

এটি অবজেক্ট অরিয়েন্টেড অর্থে পদ্ধতি সম্পর্কে কথা বলছে ।

যদিও "ফাংশন" এবং "পদ্ধতি" প্রায়শই আন্তঃসত্তা ব্যবহার করা হয়, যখন তাদের ব্যয়ের বিষয়টি আসে (যা সম্পর্কে আপনি জিজ্ঞাসা করছেন) এবং এটি সংকলনের ক্ষেত্রে আসে (যা আপনি যে প্রসঙ্গে দিয়েছেন))

বিশেষত, স্ট্যাটিক প্রেরণ বনাম গতিশীল প্রেরণ সম্পর্কে আমাদের জানতে হবে । আমি মুহুর্তের জন্য অপ্টিমাইজেশন উপেক্ষা করব।

সি এর মতো ভাষায় আমরা সাধারণত স্ট্যাটিক প্রেরণের সাথে ফাংশনগুলিকে কল করি । উদাহরণ স্বরূপ:

int foo(int x) {
  return x + 1;
}

int bar(int y) {
  return foo(y);
}

int main() {
  return bar(42);
}

সংকলক কলটি দেখলে foo(y), fooনামটি কী ফাংশনটি উল্লেখ করছে তা তা জানে , সুতরাং আউটপুট প্রোগ্রামটি সরাসরি fooফাংশনে যেতে পারে, যা বেশ সস্তা। স্ট্যাটিক প্রেরণের অর্থ এটিই ।

বিকল্পটি হ'ল ডায়নামিক প্রেরণ , যেখানে সংকলক জানে না কোন ফাংশনটি ডাকা হচ্ছে। উদাহরণস্বরূপ, এখানে কিছু হাস্কেল কোড রয়েছে (যেহেতু সি সমতুল্য অগোছালো হবে!):

foo x = x + 1

bar f x = f x

main = print (bar foo 42)

এখানে barফাংশনটি তার যুক্তি কল করছে f, যা কিছু হতে পারে। অতএব সংকলকটি barদ্রুত জাম্পের নির্দেশের সাথে কেবল সংকলন করতে পারে না , কারণ কোথায় যেতে হবে তা এটি জানে না। পরিবর্তে, আমরা যে কোডটি তৈরি করি তা কোন ফাংশনটির দিকে ইঙ্গিত করছে তা খুঁজে বের করার জন্য এটি তারপরে ঝাঁপিয়ে barপড়বে fthen ডায়নামিক প্রেরণের অর্থ এটিই ।

এই দুটি উদাহরণই ফাংশনের জন্য । আপনি পদ্ধতিগুলি উল্লেখ করেছেন , যা গতিশীল-প্রেরণিত ক্রিয়াকলাপের একটি নির্দিষ্ট স্টাইল হিসাবে ভাবা যেতে পারে। উদাহরণস্বরূপ, এখানে কিছু পাইথন রয়েছে:

class A:
  def __init__(self, x):
    self.x = x

  def foo(self):
    return self.x + 1

def bar(y):
  return y.foo()

z = A(42)
bar(z)

y.foo()কল, ডায়নামিক প্রেরণ ব্যবহার যেহেতু এটি মান আপ দেখছে fooসম্পত্তি yবস্তু, এবং কলিং যাহা এটা খুঁজে বের করে; এটি জানে না যে yক্লাস হবে A, বা Aক্লাসে একটি fooপদ্ধতি রয়েছে , তাই আমরা কেবল এটিতে লাফিয়ে উঠতে পারি না।

ঠিক আছে, এটি প্রাথমিক ধারণা। মনে রাখবেন যে আমরা সংকলন করি বা ব্যাখ্যা করি না কেন স্থির প্রেরণাগুলি গতিশীল প্রেরণের চেয়ে দ্রুত ; অন্য সব সমান হচ্ছে। ডেরেফারেন্সিংয়ে উভয় উপায়ে অতিরিক্ত ব্যয় হয়।

সুতরাং এটি কীভাবে আধুনিককে সংযোজকগুলিকে অনুকূল করে?

প্রথম বিষয় লক্ষণীয় হ'ল স্থিতিশীল প্রেরণকে আরও ভারীভাবে অনুকূল করা যায়: যখন আমরা জানি যে আমরা কোন ফাংশনটিতে যাচ্ছি, ইনলাইনিংয়ের মতো জিনিসগুলি করতে পারে। গতিশীল প্রেরণের সাথে, আমরা জানি না যে আমরা রান সময় পর্যন্ত ঝাঁপিয়ে পড়েছি, তাই আমরা করার মতো অপ্টিমাইজেশন নেই।

দ্বিতীয়ত, এটা কিছু কিছু ভাষায় সম্ভব অনুমান যেখানে কিছু গতিশীল পাঠাবে জাম্পিং শেষ হয়ে যাবে, তাই তাদের স্ট্যাটিক প্রেরণ মধ্যে নিখুত। এটি আমাদের অন্যান্য অপ্টিমাইজেশন যেমন ইনলাইনিং ইত্যাদি সম্পাদন করতে দেয়

উপরের পাইথনের উদাহরণে এই জাতীয় অনুভূতিটি হতাশ হ'ল, যেহেতু পাইথন অন্যান্য কোডগুলি শ্রেণি এবং বৈশিষ্ট্যগুলিকে ওভাররাইড করার অনুমতি দেয়, সুতরাং এটি সমস্ত ক্ষেত্রেই বহুলাংশে অনুধাবন করা কঠিন।

যদি আমাদের ভাষা আমাদের আরও বিধিনিষেধ আরোপ করতে দেয়, উদাহরণস্বরূপ কোনও টিকা ব্যবহার করে yশ্রেণিতে সীমাবদ্ধ Aকরে, তবে আমরা সেই তথ্যটি লক্ষ্য ফাংশনটি অনুমান করতে ব্যবহার করতে পারি। সাবক্লাসিংয়ের ভাষায় (যা ক্লাসগুলির সাথে প্রায় সমস্ত ভাষা!) আসলে যথেষ্ট নয়, যেহেতু yআসলে আলাদা (উপ) শ্রেণি থাকতে পারে, তাই finalঠিক কোন ফাংশনটি ডাকা হবে তা জানতে আমাদের জাভা টীকাগুলির মতো অতিরিক্ত তথ্যের প্রয়োজন হবে।

Haskell, একটি OO যেমন পণ্য ভাষা নয়, কিন্তু আমরা এর মান আবিষ্কার করতে পারেন fইনলাইনিং দ্বারা bar(যা হয় স্ট্যাটিক্যালি মধ্যে প্রেষিত) main, বদলে fooজন্য y। যেহেতু লক্ষ্য fooমধ্যে mainস্ট্যাটিক্যালি পরিচিত হয়, কল স্ট্যাটিক্যালি প্রেষিত হয়ে, এবং সম্ভবত inlined হবে এবং সম্পূর্ণরূপে দূরে অপ্টিমাইজ (যেহেতু এই ফাংশন ছোট কম্পাইলার তাদের ইনলাইন াবনা আেছ; যদিও আমরা সাধারণভাবে নির্ভর করতে পারে না )।

সুতরাং ব্যয়টি নেমে আসে:

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

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


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

2

হ্যাঁ, একটি মিসড ব্রাঞ্চের ভবিষ্যদ্বাণী আধুনিক হার্ডওয়্যারগুলির তুলনায় দশক আগে এর চেয়ে বেশি ব্যয়বহুল, তবে সংকলকগণ এটি অনুকূলকরণে অনেক বেশি স্মার্ট হয়ে উঠেছে।

উদাহরণ হিসাবে জাভা বিবেচনা করুন consider প্রথম নজরে, ফাংশন কল ওভারহেড এই ভাষায় বিশেষত প্রভাবশালী হওয়া উচিত:

  • জাভাবিয়ান কনভেনশনের কারণে ক্ষুদ্র কাজগুলি ব্যাপক আকার ধারণ করে
  • ফাংশন ডিফল্ট ভার্চুয়াল, এবং সাধারণত হয়
  • সংকলনের একক শ্রেণি; রানটাইম যে কোনও সময় নতুন ক্লাসগুলি লোড করতে সহায়তা করে, সাবক্লাসগুলি সহ যা পূর্ব মনোমরফিক পদ্ধতিগুলিকে ওভাররাইড করে

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

একটি কারণ হ'ল আধুনিক জেভিএমগুলি ইনলাইন ফাংশন অবশ্যই বিষয় হিসাবে কল করে। এটি অনুমানমূলক অন্তর্নিহিত ব্যবহার করে:

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

যে, কোড:

int x = point.getX();

এতে নতুন করে লেখা হয়

if (point.class != Point) GOTO interpreter;
x = point.x;

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

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


4
"কোনও সংকলক স্বয়ংক্রিয় ইনলাইনিং সমর্থন করতে পারে না তার কোনও সহজাত কারণ নেই" - রয়েছে। আপনি জেআইটি সংকলন সম্পর্কে কথা বলেছেন, যা স্ব-সংশোধনকারী কোডের সমান (যা কোনও ওএস সুরক্ষার কারণে প্রতিরোধ করতে পারে) এবং স্বয়ংক্রিয় প্রোফাইল-নির্দেশিত পূর্ণ-প্রোগ্রাম অপ্টিমাইজেশান করার ক্ষমতা। গতিশীল লিঙ্কিংয়ের অনুমতি দেয় এমন ভাষার জন্য একটি এওটি সংকলক কোনও কলকে ডেভ্যাচুয়ালাইজ করতে এবং ইনলাইন করতে যথেষ্ট জানেন না know ওটিওএইচ: একটি এওটি সংকলকটির যতটুকু সম্ভব তার সবটুকু অনুকূল করার সময় রয়েছে, একটি জেআইটি সংকলককে কেবল গরম স্পটে সস্তা অপ্টিমাইজেশনের উপর ফোকাস করার সময় দেয়। বেশিরভাগ ক্ষেত্রে, এটি সামান্য অসুবিধায় জেআইটি ছেড়ে দেয়।
আমন

2
আমাকে এমন একটি ওএস বলুন যা গুগল ক্রোম চালানো রোধ করে "কারণ সুরক্ষা" (ভি 8 রানওয়ার সময় জাভাস্ক্রিপ্টটি স্থানীয় কোডে সংকলন করে)। এছাড়াও, এওটি-তে ইনলাইন স্থাপন করা বেশ অন্তর্নিহিত কারণ নয় (এটি ভাষা দ্বারা নির্ধারিত হয় না, তবে আপনি আপনার সংকলকের জন্য যে আর্কিটেকচারটি চয়ন করেন) এবং গতিশীল লিঙ্কিং সংকলনের ইউনিটগুলিতে এওটি অন্তর্ভুক্ত করতে বাধা দেয় না, এটি সংকলনের মধ্যে অন্তর্নিহিতকে বাধা দেয় না it ইউনিট, যেখানে সর্বাধিক কল হয়। প্রকৃতপক্ষে, জাভা থেকে ডাইনামিক লিঙ্ক কম মাত্রায় গতিশীল লিঙ্ক ব্যবহার করে এমন ভাষায় দরকারী ইনলাইনিং তর্কযোগ্যভাবে সহজ।
মেরিটন

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

@ মেরিটন উইন্ডোজ 10 এস এবং ভিডিও গেম কনসোল অপারেটিং সিস্টেমগুলিতে তৃতীয় পক্ষের জেআইটি ইঞ্জিনগুলি অবরুদ্ধ করার ঝোঁক রয়েছে।
দামিয়ান ইয়ারিক

2

মনে রাখবেন যে কোনও পদ্ধতির কলটির দাম ভাষার উপর নির্ভর করে উল্লেখযোগ্য হতে পারে। পঠনযোগ্য কোড এবং পারফরম্যান্ট কোড লেখার মধ্যে প্রায় সবসময়ই একটি বাণিজ্য থাকে off

দুর্ভাগ্যক্রমে এটি অত্যন্ত নির্ভরশীল:

  • সংকলক সরঞ্জামচইন, জেআইটি সহ যদি থাকে তবে
  • ডোমেইন.

প্রথমত, পারফরম্যান্স অপটিমাইজেশনের প্রথম আইনটিই প্রথম প্রোফাইল । অনেকগুলি ডোমেইন রয়েছে যেখানে সফ্টওয়্যার অংশের পারফরম্যান্স পুরো স্ট্যাকের কার্য সম্পাদনের সাথে অপ্রাসঙ্গিক : ডাটাবেস কল, নেটওয়ার্ক অপারেশন, ওএস অপারেশন, ...

এর অর্থ এই যে সফ্টওয়্যারটির পারফরম্যান্স সম্পূর্ণ অপ্রাসঙ্গিক, যদিও এটি বিলম্বিতা উন্নতি না করে, সফ্টওয়্যারটি অনুকূলিতকরণের ফলে শক্তি সঞ্চয় এবং হার্ডওয়্যার সঞ্চয় (বা মোবাইল অ্যাপ্লিকেশনের জন্য ব্যাটারি সঞ্চয়) হতে পারে, যা গুরুত্বপূর্ণ।

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

সুতরাং, অনুকূলকরণের আগে, আপনার কী অপ্টিমাইজ করা হচ্ছে তা বুঝতে হবে ... এবং এটির পক্ষে এটি উপযুক্ত কিনা।


এখন, খাঁটি সফ্টওয়্যার কর্মক্ষমতা সম্পর্কিত, এটি সরঞ্জামচেইনের মধ্যে প্রচুর পরিবর্তিত হয়।

একটি ফাংশন কল দুটি খরচ আছে:

  • রান সময় ব্যয়,
  • সংকলন সময় ব্যয়।

রান সময় ব্যয় বরং সুস্পষ্ট; একটি ফাংশন কল করার জন্য একটি নির্দিষ্ট পরিমাণের কাজ করা আবশ্যক। উদাহরণস্বরূপ, x86 এ সি ব্যবহার করে একটি ফাংশন কলের প্রয়োজন হবে (1) স্ট্যাকের জন্য স্পিল রেজিস্টারগুলি, (২) নিবন্ধগুলিতে যুক্তি চাপানো, কল সম্পাদন করা এবং তারপরে (3) স্ট্যাক থেকে নিবন্ধগুলি পুনরুদ্ধার করা। কাজ জড়িত দেখতে সম্মেলন আহ্বানের এই সারাংশ দেখুন ।

এই রেজিস্টার স্পিলিং / পুনরুদ্ধার সময় একটি অ-তুচ্ছ পরিমাণ সময় লাগে (কয়েক ডজন সিপিইউ চক্র)।

সাধারণত এটি প্রত্যাশা করা হয় যে এই ব্যয়টি কার্য সম্পাদনের প্রকৃত ব্যয়ের তুলনায় তুচ্ছ হবে, তবে কিছু নিদর্শনগুলি এখানে পাল্টা উত্পাদনশীল: গেটরস, সাধারণ শর্ত দ্বারা রক্ষিত ফাংশন ইত্যাদি ...

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

একটি অপ্টিমাইজার সনাক্ত করতে পারে যে কোনও ফাংশন কলটি তুচ্ছ, এবং কলটিকে ইনলাইন করুন: মূলত, কল সাইটে ফাংশনের বডিটি অনুলিপি / আটকানো। এটি সর্বদা ভাল অপ্টিমাইজেশন হয় না (ফুলে ফুলে উঠতে পারে) তবে সাধারণভাবে সার্থক কারণ ইনলাইনিং প্রসঙ্গে প্রকাশ করে এবং প্রসঙ্গটি আরও অনুকূলিতকরণ সক্ষম করে।

একটি সাধারণ উদাহরণ হ'ল:

void func(condition: boolean) {
    if (condition) {
        doLotsOfWork();
    }
}

void call() { func(false); }

যদি funcইনলাইন করা থাকে, তবে অপ্টিমাইজারটি বুঝতে পারে যে শাখাটি কখনই নেওয়া হয় না এবং এতে অনুকূলিতকরণ callহয় void call() {}

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


উপসংহারে, আমার পরামর্শ হ'ল আগে স্পষ্টভাবে লিখুন , অকাল অ্যালগরিদমিক হতাশাকে এড়িয়ে চলা (ঘন জটিলতা বা দ্রুততর ঘনঘটিত কামড় দ্রুত) এড়িয়ে চলুন এবং তারপরে কেবল অনুকূলিতকরণের প্রয়োজনটি কেবল অনুকূলিত করুন।


1

"মনে রাখবেন যে কোনও পদ্ধতির কলটির দাম ভাষার উপর নির্ভর করে উল্লেখযোগ্য হতে পারে read পাঠযোগ্য কোড এবং পারফরম্যান্ট কোড লেখার মধ্যে প্রায় সবসময়ই একটি বাণিজ্য থাকে trade"

কোন অবস্থার অধীনে আজকাল এই উদ্ধৃত বিবৃতিটি কার্যকর আধুনিক সংকলকগুলির সমৃদ্ধ শিল্পকে দেওয়া বৈধ?

আমি শুধু ফ্ল্যাট আউট বলবো না। আমি বিশ্বাস করি যে উদ্ধৃতিটি কেবল সেখানে ফেলে দেওয়ার জন্য বেপরোয়া হবে।

অবশ্যই আমি সম্পূর্ণ সত্য কথা বলছি না, তবে আমি এতটা সত্যবাদী হওয়ার বিষয়ে চিন্তা করি না। এটি সেই ম্যাট্রিক্স সিনেমার মতোই, আমি ভুলে গিয়েছিলাম এটি 1 বা 2 বা 3 ছিল - আমি মনে করি এটি বড় স্নিগ্ধের সাথে সেক্সি ইতালিয়ান অভিনেত্রীর সাথে ছিল (আমি সত্যিই প্রথমটি পছন্দ করি না), যখন ওরাকল লেডি ক্যানু রিভসকে বলেছিলেন, "আপনাকে যা শোনার দরকার ছিল তা আমি আপনাকে কেবল বলেছিলাম", বা এই প্রভাবটির কিছু, এখন আমি এটিই করতে চাই।

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

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

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

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

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