হ্যালো! আমি ওলেক্সান্ডার ক্যালেনিউক এবং আমি একজন সি++ হলিক। আমি 17 বছর ধরে C++ এ লিখছি এবং সেই 17 বছর ধরে আমি এই ধ্বংসাত্মক আসক্তি থেকে মুক্তি পাওয়ার চেষ্টা করছি।
এটি 2005 সালে একটি 3D স্পেস সিমুলেটর ইঞ্জিন দিয়ে শুরু হয়েছিল। 2005 সালে ইঞ্জিনে C++ এর সবকিছুই ছিল। থ্রি-স্টার পয়েন্টার, নির্ভরতার আটটি স্তর এবং সর্বত্র C-স্টাইল ম্যাক্রো। সমাবেশ বিট ছিল. ইটারেটর স্টেপানোভ-স্টাইল এবং মেটা-কোড আলেকজান্ডারেস্কু-স্টাইল। কোডে সবকিছু ছিল। ব্যতীত, অবশ্যই, সবচেয়ে গুরুত্বপূর্ণ প্রশ্নের উত্তরের জন্য: কেন?
কিছুক্ষণের মধ্যে, এমনকি এই প্রশ্নের উত্তর দেওয়া হয়েছিল। শুধু "কিসের জন্য" হিসাবে নয় বরং "কীভাবে এসেছে" হিসাবে। দেখা গেল, ইঞ্জিনটি প্রায় 8 বছর ধরে 5 টি ভিন্ন দল দ্বারা লেখা হয়েছে। এবং প্রতিটি দল তাদের পছন্দের ফ্যাড নিয়ে এসেছে প্রকল্পে পুরানো কোডটিকে নতুন স্টাইলযুক্ত র্যাপারে মোড়ানো এবং এটি করার সময় কার্যকারিতা মাত্র 10-20 মাইক্রোকারম্যাক যোগ করেছে।
প্রথমে, আমি সততার সাথে প্রতিটি ছোট জিনিস গুম করার চেষ্টা করছিলাম। এটি একটি তৃপ্তিদায়ক অভিজ্ঞতা ছিল না, মোটেই নয় এবং কিছু সময়ে, আমি হাল ছেড়ে দিয়েছিলাম। আমি তখনও কাজগুলো বন্ধ করছিলাম, এবং বাগ ঠিক করছিলাম। বলতে পারি না যে আমি খুব উত্পাদনশীল ছিলাম, তবে বরখাস্ত না হওয়ার জন্য যথেষ্ট। কিন্তু তারপরে আমার বস আমাকে জিজ্ঞাসা করলেন: "আপনি কি অ্যাসেম্বলি থেকে জিএলএসজিতে কিছু শেডার কোড পুনরায় লিখতে চান?" আমি ভেবেছিলাম ঈশ্বর জানেন এই GLSL দেখতে কেমন কিন্তু এটি সম্ভবত C++ এর চেয়ে খারাপ হতে পারে না এবং হ্যাঁ বলেছে। এটা খারাপ ছিল না.
এবং এই ধরনের একটি প্যাটার্ন হয়ে ওঠে. আমি তখনও বেশির ভাগই C++ এ লিখতাম কিন্তু প্রতিবার কেউ আমাকে জিজ্ঞেস করত "আপনি কি সেই নন-C++ জিনিসটি করতে চান?" আমি নিশ্চিত ছিলাম!" এবং আমি যে জিনিসটি যাই হোক না কেন তা করেছি। আমি C89, MASM32, C#, PHP, Delphi, ActionScript, JavaScript, Erlang, Python, Haskell, D, Rust, এবং এমনকি সেই চরম খারাপ InstallShield স্ক্রিপ্টিং ভাষাতে লিখেছি। আমি ভিজ্যুয়ালবেসিক, ব্যাশে এবং কয়েকটি মালিকানাধীন ভাষায় লিখেছি, আমি এমনকি আইনগতভাবে কথা বলতে পারি না। এমনকি আমি দুর্ঘটনাক্রমে নিজেই একটি তৈরি করেছি। আমি গেম ডিজাইনারদের রিসোর্স লোডিং স্বয়ংক্রিয় করতে সাহায্য করার জন্য একটি সাধারণ লিস্প-স্টাইল দোভাষী তৈরি করেছি এবং ছুটিতে গিয়েছিলাম। আমি যখন ফিরে আসি, তখন তারা এই দোভাষীতে পুরো গেমের দৃশ্য লিখছিল তাই আমাদের অন্তত, প্রকল্পের শেষ পর্যন্ত এটি সমর্থন করতে হয়েছিল।
তাই গত 17 বছর ধরে, আমি সৎভাবে C++ ছেড়ে দেওয়ার চেষ্টা করছিলাম কিন্তু প্রতিবার, আমি একটি নতুন চকচকে জিনিস চেষ্টা করার পরে, আমি ফিরে আসছি। তবুও, আমি মনে করি যে C++ এ লেখা একটি খারাপ অভ্যাস। এটি অনিরাপদ, এটি যতটা কার্যকর বলে মনে করা হয় ততটা কার্যকর নয় এবং এটি এমন জিনিসগুলিতে একটি প্রোগ্রামারের মানসিক ক্ষমতার ভয়ানক পরিমাণ নষ্ট করে যেগুলির সফ্টওয়্যার তৈরির সাথে কোনও সম্পর্ক নেই৷ আপনি কি জানেন যে MSVC uint16_t(50000) + uin16_t(50000) == -1794967296
? তুমি কি জানো কেন? হ্যাঁ, এটাই ভেবেছিলাম।
আমি বিশ্বাস করি যে দীর্ঘকালের C++ প্রোগ্রামারদের নৈতিক দায়িত্ব হল তরুণ প্রজন্মকে C++ কে তাদের পেশা বানানো থেকে নিরুৎসাহিত করা কারণ এটি মদ্যপদের নৈতিক দায়িত্ব যারা যুবকদের বিপদ সম্পর্কে সতর্ক করতে ছাড়তে পারে না।
কিন্তু আমি কেন ছাড়তে পারি না? কি ব্যাপার? ব্যাপারটি হল, কোনো ভাষাই, বিশেষ করে তথাকথিত "C++ হত্যাকারী" আধুনিক বিশ্বে C++ এর থেকে কোনো প্রকৃত সুবিধা দেয় না। এই সমস্ত নতুন ভাষাগুলি বেশিরভাগই তাদের নিজস্ব ভালোর জন্য একজন প্রোগ্রামারকে আটকে রাখার উপর দৃষ্টি নিবদ্ধ করে। এটা ঠিক, বাদে খারাপ প্রোগ্রামারদের সাথে ভালো কোড লেখা XX শতাব্দীর একটি সমস্যা যখন ট্রানজিস্টর প্রতি 18 মাসে দ্বিগুণ বৃদ্ধি পায় এবং প্রোগ্রামারদের হেডকাউন্ট প্রতি 5 বছরে দ্বিগুণ বৃদ্ধি পায়।
আমরা 2023-এ বাস করছি। আমাদের বিশ্বের ইতিহাসে আগের চেয়ে অনেক বেশি অভিজ্ঞ প্রোগ্রামার রয়েছে। এবং আমাদের এখন আগের চেয়ে বেশি দক্ষ সফ্টওয়্যার দরকার।
XX শতাব্দীতে জিনিসগুলি সহজ ছিল। আপনার কাছে একটি ধারণা আছে, আপনি এটিকে কিছু UI এ মোড়ানো এবং এটি একটি ডেস্কটপ পণ্য হিসাবে বিক্রি করুন৷ এটা কি ধীর? কে পাত্তা দেয়! আঠারো মাসের মধ্যে ডেস্কটপ 2গুণ দ্রুত হয়ে যাবে। যা গুরুত্বপূর্ণ তা হল বাজারে প্রবেশ করা, বৈশিষ্ট্য বিক্রি শুরু করা এবং বিশেষত বাগ ছাড়াই। সেই জলবায়ুতে, নিশ্চিত, যদি একটি কম্পাইলার প্রোগ্রামারদের বাগ তৈরি করা থেকে বিরত রাখে - ভাল! কারণ বাগগুলি নগদ নিয়ে আসে না, এবং আপনাকে আপনার প্রোগ্রামারদের অর্থ প্রদান করতে হবে তারা যাইহোক বৈশিষ্ট্য বা বাগ যোগ করে।
এখন জিনিস ভিন্ন। আপনার একটি ধারণা আছে, আপনি এটি একটি ডকার পাত্রে মোড়ানো এবং একটি মেঘে চালান। এখন আপনি আপনার সফ্টওয়্যার চালনা করা লোকদের কাছ থেকে আপনার রাজস্ব পাবেন যদি এটি তাদের সমস্যাগুলি দূর করে দেয়। এমনকি যদি এটি একটি কাজ করে তবে এটি সঠিকভাবে করে, আপনি অর্থ প্রদান করবেন। শুধুমাত্র এটির একটি নতুন সংস্করণ বিক্রি করার জন্য আপনাকে আপনার পণ্যটিকে তৈরি-আপ বৈশিষ্ট্যগুলির সাথে স্টাফ করতে হবে না। অন্যদিকে, যিনি আপনার কোডের অকার্যকরতার জন্য অর্থ প্রদান করেন তিনি এখন নিজেই। প্রতিটি সাবঅপ্টিমাল রুটিন আপনার AWS বিলে দেখায়।
তাই নতুন জলবায়ুতে, আপনার এখন কম বৈশিষ্ট্য প্রয়োজন, তবে আপনি যা পেয়েছেন তার জন্য আরও ভাল পারফরম্যান্স।
এবং হঠাৎ দেখা গেল যে সমস্ত "C++ হত্যাকারী", এমনকি এগুলিকে আমি আন্তরিকভাবে ভালবাসি এবং মরিচা, জুলিয়া এবং ডি এর মতো সম্মান করি, XXI শতাব্দীর সমস্যার সমাধান করে না। তারা এখনও XX এ আটকে আছে। তারা আপনাকে কম বাগ সহ আরও বৈশিষ্ট্য লিখতে সহায়তা করে, তবে আপনার ভাড়া করা হার্ডওয়্যার থেকে একেবারে শেষ ফ্লপটি চেপে নেওয়ার প্রয়োজন হলে সেগুলি খুব বেশি সাহায্য করে না।
তারা আপনাকে C++ এর তুলনায় প্রতিযোগিতামূলক সুবিধা দেয় না। অথবা, এই বিষয়ে, এমনকি একে অপরের উপর। তাদের বেশিরভাগ, উদাহরণস্বরূপ, মরিচা, জুলিয়া এবং ক্ল্যান্ড এমনকি একই ব্যাকএন্ড ভাগ করে নেয়। আপনি একটি গাড়ী রেস জিততে পারবেন না যদি আপনি একই গাড়ী শেয়ার করেন।
সুতরাং, কোন প্রযুক্তিগুলি আপনাকে C++ বা সাধারণভাবে বলতে গেলে, সমস্ত প্রথাগত আগাম-সময়ের কম্পাইলারগুলির তুলনায় একটি প্রতিযোগিতামূলক সুবিধা দেয়? ভাল প্রশ্ন. খুশি আপনি জিজ্ঞাসা.
কিন্তু আমরা স্পাইরালের সাথে যাওয়ার আগে, আপনার অন্তর্দৃষ্টি কতটা ভাল কাজ করে তা পরীক্ষা করা যাক। আপনি কোনটি দ্রুত বলে মনে করেন: একটি স্ট্যান্ডার্ড C++ সাইন ফাংশন, নাকি সাইনের 4-টুকরো বহুপদী মডেল?
auto y = std::sin(x); // vs. y = -0.000182690409228785*x*x*x*x*x*x*x +0.00830460224186793*x*x*x*x*x -0.166651012143690*x*x*x +x;
পরের প্রশ্ন. কি দ্রুত কাজ করে, শর্ট সার্কিটিং সহ লজিক্যাল ক্রিয়াকলাপ ব্যবহার করে, বা এটি এড়াতে একটি কম্পাইলারকে চালান করে এবং প্রচুর পরিমাণে লজিক্যাল এক্সপ্রেশন গণনা করে?
if (xs[i] == 1 && xs[i+1] == 1 && xs[i+2] == 1 && xs[i+3] == 1) // xs are bools stored as ints // vs. inline int sq(int x) { return x*x; } if(sq(xs[i] - 1) + sq(xs[i+1] - 1) + sq(xs[i+2] - 1) + sq(xs[i+3] - 1) == 0)
এবং আরো একটি. কি বাছাই দ্রুত ত্রিপল: একটি অদলবদল-বাছাই বা একটি সূচক-বাছাই?
if(s[0] > s[1]) swap(s[0], s[1]); if(s[1] > s[2]) swap(s[1], s[2]); if(s[0] > s[1]) swap(s[0], s[1]); // vs. const auto a = s[0]; const auto b = s[1]; const auto c = s[2]; s[int(a > b) + int(a > c)] = a; s[int(b >= a) + int(b > c)] = b; s[int(c >= a) + int(c >= b)] = c;
আপনি যদি সমস্ত প্রশ্নের উত্তর নির্ণায়কভাবে এবং এমনকি চিন্তা বা গুগলিং ছাড়াই দেন, তাহলে আপনার অন্তর্দৃষ্টি আপনাকে ব্যর্থ করেছে। আপনি ফাঁদ দেখতে পাননি. এই প্রশ্নের কোনটিরই প্রসঙ্গ ছাড়া সুনির্দিষ্ট উত্তর নেই।
কোন CPU বা GPU কোড টার্গেট করে? কোন কম্পাইলার কোড তৈরি করার কথা? কোন কম্পাইলার অপ্টিমাইজেশান চালু এবং কোনটি বন্ধ? আপনি শুধুমাত্র তখনই ভবিষ্যদ্বাণী করা শুরু করতে পারেন যখন আপনি সেই সমস্ত কিছু জানেন, বা আরও ভালভাবে, প্রতিটি নির্দিষ্ট সমাধানের জন্য রান টাইম পরিমাপ করেন।
একটি বহুপদী মডেল স্ট্যান্ডার্ড সাইনের চেয়ে 3 গুণ দ্রুততর হয় যদি -O2 -march=native সহ ক্ল্যাং 11 দিয়ে নির্মিত হয় এবং Intel Core i7-9700F-এ চলে। কিন্তু যদি --use-fast-math- এর সাথে nvcc এবং GeForce GTX 1050 Ti Mobile-এর GPU-তে তৈরি করা হয়, তাহলে আদর্শ সাইন মডেলের চেয়ে 10 গুণ দ্রুত।
ভেক্টরাইজড পাটিগণিতের জন্য ট্রেডিং শর্ট-সার্কিট লজিক i7 এও অর্থপূর্ণ। স্নিপেটটি দ্বিগুণ দ্রুত কাজ করে। কিন্তু একই ক্ল্যাং এবং -O2 সহ ARMv7-এ, স্ট্যান্ডার্ড লজিক মাইক্রো-অপ্টিমাইজেশনের চেয়ে 25% দ্রুত ।
এবং ইনডেক্স-সর্ট বনাম সোয়াপ-সর্টের সাথে, ইন্টেলে ইনডেক্স-সর্ট 3 গুণ দ্রুত এবং GeForce-এ সোয়াপ-সর্ট 3 গুণ দ্রুত ।
তাই প্রিয় মাইক্রো-অপ্টিমাইজেশানগুলি আমরা সকলেই খুব পছন্দ করি, উভয়ই আমাদের কোডকে ফ্যাক্টর 3 দ্বারা গতি বাড়াতে পারে এবং 90% কমিয়ে দিতে পারে। এটা সব প্রেক্ষাপট উপর নির্ভর করে. এটি কতই না চমৎকার হবে যদি একটি কম্পাইলার আমাদের জন্য সেরা বিকল্পটি বেছে নিতে পারে যাতে আমরা যখন বিল্ড টার্গেট পরিবর্তন করি তখন ইনডেক্স-সর্ট অলৌকিকভাবে সোয়াপ-সর্টে পরিণত হয়। কিন্তু তা পারেনি।
এমনকি যদি আমরা কম্পাইলারকে সাইনকে বহুপদী মডেল হিসাবে পুনরায় প্রয়োগ করতে, গতির জন্য নির্ভুলতা বাণিজ্য করার অনুমতি দিই, তবুও এটি আমাদের লক্ষ্য নির্ভুলতা জানে না। C++ এ, আমরা বলতে পারি না যে "এই ফাংশনটিতে সেই ত্রুটি থাকতে দেওয়া হয়েছে"। আমাদের কাছে যা আছে তা হল কম্পাইলার ফ্ল্যাগ যেমন "--ব্যবহার-দ্রুত-গণিত" এবং শুধুমাত্র একটি অনুবাদ ইউনিটের সুযোগে।
দ্বিতীয় উদাহরণে, কম্পাইলার জানে না যে আমাদের মানগুলি 0 বা 1 এর মধ্যে সীমাবদ্ধ এবং সম্ভবত আমরা যে অপ্টিমাইজেশন করতে পারি তা প্রস্তাব করতে পারে না। আমরা সম্ভবত একটি সঠিক বুল টাইপ ব্যবহার করে এটিতে ইঙ্গিত করতে পারতাম তবে এটি সম্পূর্ণ ভিন্ন সমস্যা হত।
এবং তৃতীয় উদাহরণে, কোডের টুকরোগুলি সমার্থক হিসাবে স্বীকৃত হওয়ার জন্য সম্পূর্ণ আলাদা। আমরা খুব বেশি কোড বিস্তারিত. যদি এটি শুধুমাত্র std::sort হত, তাহলে এটি ইতিমধ্যেই কম্পাইলারকে অ্যালগরিদম বেছে নেওয়ার আরও স্বাধীনতা দিত। কিন্তু এটি সূচী-বাছাই নয় অদলবদল বাছাই করে না কারণ তারা উভয়ই বড় অ্যারেতে অদক্ষ এবং std::sort একটি জেনেরিক পুনরাবৃত্তিযোগ্য ধারক দিয়ে কাজ করে।
আর এভাবেই আমরা স্পাইরালে যাই। এটি কার্নেগি মেলন বিশ্ববিদ্যালয় এবং Eidgenössische Technische Hochschule Zürich এর একটি যৌথ প্রকল্প। TL&DR: সিগন্যাল প্রসেসিং বিশেষজ্ঞরা তাদের পছন্দের অ্যালগরিদমগুলিকে হাতে করে প্রতিটি নতুন হার্ডওয়্যারের জন্য পুনরায় লিখতে বিরক্ত হয়েছিলেন এবং একটি প্রোগ্রাম লিখেছিলেন যা তাদের জন্য এটি কাজ করে। প্রোগ্রামটি একটি অ্যালগরিদমের উচ্চ-স্তরের বর্ণনা এবং হার্ডওয়্যার আর্কিটেকচারের একটি বিশদ বিবরণ নেয় এবং কোডটিকে অপ্টিমাইজ করে যতক্ষণ না এটি নির্দিষ্ট হার্ডওয়্যারের জন্য সবচেয়ে কার্যকর অ্যালগরিদম বাস্তবায়ন করে।
Fortran এবং alikes মধ্যে একটি গুরুত্বপূর্ণ পার্থক্য, সর্পিল সত্যিই গাণিতিক অর্থে একটি অপ্টিমাইজেশান সমস্যা সমাধান করে। এটি রান টাইমকে একটি টার্গেট ফাংশন হিসাবে সংজ্ঞায়িত করে এবং হার্ডওয়্যার আর্কিটেকচার দ্বারা সীমিত বাস্তবায়ন ভেরিয়েন্টের ফ্যাক্টর স্পেসের বৈশ্বিক সর্বোত্তম সন্ধান করে। এই কিছু কম্পাইলার আসলে না.
একটি কম্পাইলার সত্যিকারের সর্বোত্তম সন্ধান করে না। এটি প্রোগ্রামারদের দ্বারা শেখানো হিউরিস্টিকস দ্বারা নির্দেশিত কোডটিকে অপ্টিমাইজ করে। মূলত একটি কম্পাইলার সর্বোত্তম সমাধান অনুসন্ধানকারী একটি মেশিন হিসাবে কাজ করে না, এটি একটি সমাবেশ প্রোগ্রামার হিসাবে কাজ করে। একটি ভাল কম্পাইলার একটি ভাল সমাবেশ প্রোগ্রামারের মত কাজ করে, কিন্তু এটিই।
সর্পিল একটি গবেষণা প্রকল্প। এটি সুযোগ এবং বাজেটে সীমিত। কিন্তু ফলাফল এটি দেখায় ইতিমধ্যে চিত্তাকর্ষক. দ্রুত ফুরিয়ার ট্রান্সফর্মে, তাদের সমাধান এমকেএল এবং এফএফটিডাব্লিউ উভয় বাস্তবায়নকে নিষ্পত্তিমূলকভাবে অতিক্রম করে। তাদের কোড ~2x দ্রুত। এমনকি ইন্টেলেও।
কৃতিত্বের স্কেল হাইলাইট করার জন্য, MKL হল Intel-এর ম্যাথ কার্নেল লাইব্রেরি, তাই যারা তাদের হার্ডওয়্যার সবচেয়ে বেশি ব্যবহার করতে জানে। এবং WWTF AKA "পশ্চিমে দ্রুততম ফুরিয়ার ট্রান্সফর্ম" হল একটি উচ্চ বিশেষায়িত লাইব্রেরি যারা অ্যালগরিদমটি সবচেয়ে ভাল জানেন। তারা যা করে তাতে তারা উভয়েই চ্যাম্পিয়ন এবং স্পাইরাল তাদের উভয়কে দ্বিগুণ হারায় তা বিস্ময়কর।
যখন অপ্টিমাইজেশান প্রযুক্তি স্পাইরাল ব্যবহার চূড়ান্ত এবং বাণিজ্যিকীকরণ করা হবে, তখন শুধুমাত্র C++ নয়, মরিচা, জুলিয়া, এমনকি Fortran এমন প্রতিযোগিতার মুখোমুখি হবে যা তারা আগে কখনও মুখোমুখি হয়নি। উচ্চ-স্তরের অ্যালগরিদম বর্ণনা ভাষায় লিখলে আপনার কোড 2x দ্রুততর হলে কেন কেউ C++ এ লিখবে?
সর্বোত্তম প্রোগ্রামিং ল্যাঙ্গুয়েজ হল যা আপনি ইতিমধ্যেই ভাল জানেন। বেশ কয়েক দশক ধরে, বেশিরভাগ প্রোগ্রামারদের জন্য সবচেয়ে পরিচিত ভাষা হল সি। এটি টিআইওবিই সূচকে নেতৃত্ব দেয় এবং অন্যান্য সি-লাইকগুলি শক্তভাবে শীর্ষ 10 তে স্থান করে নেয়। তবে, মাত্র দুই বছর আগে এমন কিছু ঘটেছিল যা শোনা যায়নি। সি অন্য কিছুতে তার প্রথম স্থান দিয়েছে।
"অন্য কিছু" পাইথন বলে মনে হয়েছিল। একটি ভাষা 90 এর দশকে কেউ গুরুত্ব সহকারে নেয়নি কারণ এটি ছিল আরেকটি স্ক্রিপ্টিং ভাষা যা আমাদের ইতিমধ্যে প্রচুর ছিল।
কেউ বলবে: "বাহ, পাইথন ধীর", এবং বোকার মতো দেখবে কারণ এটি পরিভাষাগত বাজে কথা। শুধু একটি accordion বা একটি ফ্রাইং প্যান মত, একটি ভাষা সহজভাবে দ্রুত বা ধীর হতে পারে না. অ্যাকর্ডিয়নের গতি যেমন কে বাজাচ্ছে তার উপর নির্ভর করে, তেমনি একটি ভাষার "গতি" নির্ভর করে এর কম্পাইলার কতটা দ্রুত তার উপর।
"কিন্তু পাইথন একটি সংকলিত ভাষা নয়" কেউ চালিয়ে যেতে পারে, এবং আবার ভুল ফায়ার করতে পারে। এখানে প্রচুর পাইথন কম্পাইলার রয়েছে এবং তাদের মধ্যে সবচেয়ে প্রতিশ্রুতিশীল একটি পাইথন স্ক্রিপ্ট। আমাকে বিস্তারিত বলতে দাও.
আমার একবার একটি প্রকল্প ছিল। একটি 3D-প্রিন্টিং সিমুলেশন যা মূলত পাইথনে লেখা হয়েছিল এবং তারপর C++ "পারফরম্যান্সের জন্য" তে পুনরায় লেখা হয়েছিল, এবং তারপর GPU-তে পোর্ট করা হয়েছিল, আমি আসার আগে সেগুলি সবই। তারপর আমি বিল্ডটিকে লিনাক্সে পোর্ট করতে কয়েক মাস ব্যয় করেছি, এর জন্য GPU কোড অপ্টিমাইজ করে Tesla M60 যেহেতু এই সময়ে AWS-এ এটি সবচেয়ে সস্তা ছিল, এবং C++/CU কোডের সমস্ত পরিবর্তনগুলিকে পাইথনের আসল কোডের সাথে বৈধতা দিচ্ছে। তাই আমি সাধারণত জ্যামিতিক অ্যালগরিদম তৈরিতে বিশেষায়িত জিনিসগুলি ছাড়া সবকিছুই করেছি।
এবং অবশেষে যখন আমার সবকিছু কাজ করে, ব্রেমেনের একজন পার্ট-টাইমার ছাত্র আমাকে ডেকে জিজ্ঞাসা করেছিল: "তাই আপনি ভিন্ন ভিন্ন জিনিসগুলিতে ভাল, আপনি কি আমাকে জিপিইউতে একটি অ্যালগরিদম চালাতে সাহায্য করতে পারেন?" অবশ্যই! আমি তাকে CUDA, CMake, Linux বিল্ড, টেস্টিং এবং অপ্টিমাইজ করার বিষয়ে বলেছিলাম; হয়তো এক ঘন্টা কথা বলে কেটেছে। তিনি খুব বিনয়ের সাথে সব শুনেছিলেন, কিন্তু শেষে বলেছিলেন: "এটি সবই খুব আকর্ষণীয়, তবে আমার একটি খুব নির্দিষ্ট প্রশ্ন আছে। তাই আমার একটি ফাংশন আছে, আমি এর সংজ্ঞার আগে @cuda.jit লিখেছি, এবং পাইথন অ্যারে সম্পর্কে কিছু বলে এবং কার্নেল কম্পাইল করে না। আপনি কি জানেন এখানে কি সমস্যা হতে পারে?"
আমি জানতাম না। একদিনেই সে নিজেই বুঝে ফেলল। স্পষ্টতই, Numba নেটিভ পাইথন তালিকার সাথে কাজ করে না এটি শুধুমাত্র NumPy অ্যারেতে ডেটা গ্রহণ করে। তাই তিনি এটি বের করলেন এবং GPU-তে তার অ্যালগরিদম চালালেন। পাইথনে। আমি মাস কাটিয়েছি তার কোন সমস্যা ছিল না. আপনি কি এটি লিনাক্সে চান? কোনো সমস্যা নেই, শুধু লিনাক্সে চালান। আপনি কি এটি পাইথন কোডের সাথে সামঞ্জস্যপূর্ণ হতে চান? কোন সমস্যা নেই, এটি পাইথন কোড। আপনি কি লক্ষ্য প্ল্যাটফর্মের জন্য অপ্টিমাইজ করতে চান? আবার সমস্যা নেই। Numba আপনি যে প্ল্যাটফর্মে কোড চালান তার জন্য কোডটি অপ্টিমাইজ করবে কারণ এটি সময়ের আগে কম্পাইল হয় না, এটি ইতিমধ্যেই স্থাপন করা হলে এটি চাহিদা অনুযায়ী কম্পাইল করে।
যে সন্ত্রস্ত না? আচ্ছা, না। যাইহোক আমার জন্য না. আমি C++ সমস্যা সমাধানের সাথে কয়েক মাস কাটিয়েছি যেগুলি Numba-এ কখনও ঘটে না, এবং ব্রেমেনের একজন খণ্ড-টাইমার কয়েক দিনের মধ্যে একই জিনিস তৈরি করে। নুম্বার সাথে তার প্রথম অভিজ্ঞতা না হলে এটি কয়েক ঘন্টা হতে পারে। তাহলে এই Numba কি? এটা কি ধরনের জাদু?
জাদুবিদ্যা নেই। পাইথন ডেকোরেটররা কোডের প্রতিটি অংশকে আপনার জন্য তার বিমূর্ত সিনট্যাক্স ট্রিতে পরিণত করে, যাতে আপনি এটি দিয়ে যা চান তা করতে পারেন। Numba হল একটি পাইথন লাইব্রেরি যা এটির যেকোনো ব্যাকএন্ড এবং এটি সমর্থন করে এমন যেকোনো প্ল্যাটফর্মের জন্য বিমূর্ত সিনট্যাক্স ট্রি কম্পাইল করতে চায়। আপনি যদি সিপিইউ কোরে ব্যাপকভাবে সমান্তরাল ফ্যাশনে চালানোর জন্য আপনার পাইথন কোড কম্পাইল করতে চান - শুধু নুম্বাকে এটিকে কম্পাইল করতে বলুন। আপনি যদি GPU-তে কিছু চালাতে চান, আবার, আপনাকে শুধুমাত্র জিজ্ঞাসা করা উচিত ।
@cuda.jit def matmul(A, B, C): """Perform square matrix multiplication of C = A * B.""" i, j = cuda.grid(2) if i < C.shape[0] and j < C.shape[1]: tmp = 0. for k in range(A.shape[1]): tmp += A[i, k] * B[k, j] C[i, j] = tmp
Numba পাইথন কম্পাইলারগুলির মধ্যে একটি যা C++ অপ্রচলিত করে তোলে। তাত্ত্বিকভাবে, যাইহোক, এটি C++ এর চেয়ে ভাল নয় কারণ এটি একই ব্যাকএন্ড ব্যবহার করে। এটি GPU প্রোগ্রামিং এর জন্য CUDA এবং CPU এর জন্য LLVM ব্যবহার করে। অনুশীলনে, যেহেতু প্রতিটি নতুন আর্কিটেকচারের জন্য আগে থেকে পুনর্নির্মাণের প্রয়োজন হয় না, তাই Numba সমাধানগুলি প্রতিটি নতুন হার্ডওয়্যার এবং এর উপলব্ধ অপ্টিমাইজেশানগুলির সাথে আরও ভালভাবে মানিয়ে নেয়।
অবশ্যই, স্পাইরালের মতো একটি পরিষ্কার পারফরম্যান্স সুবিধা থাকা ভাল হবে। কিন্তু সর্পিল হল একটি গবেষণা প্রকল্প, এটি C++ কে মেরে ফেলতে পারে কিন্তু শুধুমাত্র শেষ পর্যন্ত, এবং শুধুমাত্র যদি এটি ভাগ্যবান হয়। পাইথনের সাথে Numba এখনই, রিয়েল-টাইমে C++ শ্বাসরোধ করে। কারণ আপনি যদি পাইথনে লিখতে পারেন এবং C++ এর পারফরম্যান্স পেতে পারেন, তাহলে আপনি কেন C++ এ লিখতে চান?
আরেকটা খেলা খেলি। আমি আপনাকে কোডের তিনটি টুকরো দেব, এবং আপনি অনুমান করবেন যে তাদের মধ্যে কোনটি, বা আরও বেশি, সমাবেশে লেখা আছে। এখানে তারা:
invoke RegisterClassEx, addr wc ; register our window class invoke CreateWindowEx,NULL, ADDR ClassName, ADDR AppName,\ WS_OVERLAPPEDWINDOW,\ CW_USEDEFAULT, CW_USEDEFAULT,\ CW_USEDEFAULT, CW_USEDEFAULT,\ NULL, NULL, hInst, NULL mov hwnd,eax invoke ShowWindow, hwnd,CmdShow ; display our window on desktop invoke UpdateWindow, hwnd ; refresh the client area .while TRUE ; Enter message loop invoke GetMessage, ADDR msg,NULL,0,0 .break .if (!eax) invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg .endw
(module (func $add (param $lhs i32) (param $rhs i32) (result i32) get_local $lhs get_local $rhs i32.add) (export "add" (func $add)))
v0 = my_vector // we want the horizontal sum of this int64 r0 = get_len ( v0 ) int64 r0 = round_u2 ( r0 ) float v0 = set_len ( r0 , v0 ) while ( uint64 r0 > 4) { uint64 r0 >>= 1 float v1 = shift_reduce ( r0 , v0 ) float v0 = v1 + v0 }
তাহলে কোনটি, বা একাধিক, সমাবেশে? তিনজনই যদি মনে করেন, অভিনন্দন! আপনার অন্তর্দৃষ্টি ইতিমধ্যে অনেক ভাল অর্জিত হয়েছে!
প্রথমটি MASM32-এ। এটি একটি ম্যাক্রোঅ্যাসেম্বলার যার মধ্যে "if" এবং "while" এর লোকেরা নেটিভ উইন্ডোজ অ্যাপ্লিকেশন লেখে। এটা ঠিক, "লিখতে ব্যবহৃত" নয়, "লিখতে" আজ পর্যন্ত। মাইক্রোসফ্ট উদ্যোগের সাথে Win32 API-এর সাথে উইন্ডোজের পশ্চাৎগামী সামঞ্জস্য রক্ষা করে তাই সমস্ত MASM32 প্রোগ্রামগুলি আধুনিক পিসিতেও ভাল কাজ করে।
বিদ্রূপাত্মক কি, PDP-7 থেকে PDP-11-এ UNIX অনুবাদকে সহজ করার জন্য C আবিষ্কার করা হয়েছিল। এটি 70 এর দশকের হার্ডওয়্যার আর্কিটেকচারের ক্যামব্রিয়ান বিস্ফোরণ থেকে বাঁচতে সক্ষম একটি পোর্টেবল অ্যাসেম্বলার হিসাবে ডিজাইন করা হয়েছিল। কিন্তু XXI শতাব্দীতে, হার্ডওয়্যার আর্কিটেকচারটি এতটাই মন্থরভাবে বিকশিত হয়েছে, 20 বছর আগে MASM32-এ আমি যে প্রোগ্রামগুলি লিখেছিলাম সেগুলি আজকে একত্রিত হয় এবং নিখুঁতভাবে চলে, কিন্তু আমার কোনো আস্থা নেই যে C++ অ্যাপ্লিকেশন যা আমি গত বছর CMake 3.21 দিয়ে তৈরি করেছি তা আজ CMake-এর সাথে তৈরি হবে। 3.25।
কোডের দ্বিতীয় অংশ হল ওয়েব সমাবেশ। এটি এমনকি একটি ম্যাক্রো অ্যাসেম্বলারও নয়, এতে "যদি" এবং "যখন" নেই, এটি আপনার ব্রাউজারের জন্য একটি মানব-পাঠযোগ্য মেশিন কোড। অথবা অন্য কোনো ব্রাউজার। ধারণাগতভাবে, যেকোনো ব্রাউজার।
ওয়েব অ্যাসেম্বলি কোড আপনার হার্ডওয়্যার আর্কিটেকচারের উপর নির্ভর করে না। এটি যে মেশিনটি পরিবেশন করে তা হল বিমূর্ত, ভার্চুয়াল, সর্বজনীন, আপনি যা চান তা বলুন। আপনি যদি এই পাঠ্যটি পড়তে পারেন, আপনি ইতিমধ্যে আপনার শারীরিক মেশিনে একটি পেয়েছেন।
কিন্তু কোডের সবচেয়ে আকর্ষণীয় অংশ হল তৃতীয়টি। এটি ফরওয়ার্ডকম – একজন অ্যাসেম্বলার অ্যাগনের ফগ, সি++ এবং অ্যাসেম্বলি অপ্টিমাইজেশন ম্যানুয়ালগুলির একজন বিখ্যাত লেখক, প্রস্তাব করেছেন। ঠিক যেমন ওয়েব অ্যাসেম্বলির সাথে, প্রস্তাবটি কেবলমাত্র পশ্চাৎপদ নয় বরং অগ্রবর্তী সামঞ্জস্যতা সক্ষম করার জন্য ডিজাইন করা নির্দেশাবলীর সার্বজনীন সেটের মতো একটি সংযোজনকারীকে কভার করে না। অত: পর নামটা. ForwardCom-এর পুরো নাম হল “ একটি ওপেন ফরওয়ার্ড-সামঞ্জস্যপূর্ণ নির্দেশনা সেট আর্কিটেকচার ”। অন্য কথায়, এটি শান্তি চুক্তির প্রস্তাব হিসাবে সমাবেশের প্রস্তাব নয়।
আমরা জানি যে সমস্ত সাধারণ স্থাপত্য পরিবার: x64, ARM, এবং RISC-V-এর বিভিন্ন নির্দেশনা সেট রয়েছে। কিন্তু এভাবে রাখার সঠিক কারণ কেউ জানে না। সব আধুনিক প্রসেসর, সম্ভবত সবচেয়ে সহজ বাদে, আপনি যে কোডটি দিয়ে এটিকে ফিড করেন সেটি চালান না বরং তারা আপনার ইনপুটটি অনুবাদ করে মাইক্রোকোড চালান। সুতরাং এটি শুধুমাত্র M1ই নয় যার ইন্টেলের জন্য একটি পশ্চাদমুখী সামঞ্জস্য স্তর রয়েছে, প্রতিটি প্রসেসরের নিজস্ব পূর্ববর্তী সংস্করণগুলির জন্য একটি পশ্চাদমুখী সামঞ্জস্য স্তর রয়েছে৷
তাহলে কি আর্কিটেকচার ডিজাইনারদের অনুরূপ স্তরে একমত হতে বাধা দেয় কিন্তু ফরোয়ার্ড সামঞ্জস্যের জন্য? কোম্পানির দ্বন্দ্বমূলক উচ্চাকাঙ্ক্ষা ছাড়াও সরাসরি প্রতিযোগিতায়, কিছুই নয়। কিন্তু যদি প্রসেসর নির্মাতারা কোনো এক সময়ে প্রতি অন্য প্রতিযোগীর প্রতি একটি নতুন সামঞ্জস্যপূর্ণ স্তর প্রয়োগ করার পরিবর্তে একটি সাধারণ নির্দেশনা সেট করতে স্থির হয়, ফরওয়ার্ডকম সমাবেশ প্রোগ্রামিংকে মূলধারায় ফিরিয়ে নিয়ে যাবে। এই ফরোয়ার্ড কম্প্যাটিবিলিটি লেয়ারটি সেখানে থাকা প্রতিটি অ্যাসেম্বলি প্রোগ্রামারের খারাপ নিউরোসিসকে নিরাময় করবে: "কি হবে যদি আমি এই নির্দিষ্ট আর্কিটেকচারের জন্য ওয়ান-ইন-এ-লাইফটাইম কোড লিখি, এবং এই নির্দিষ্ট আর্কিটেকচারটি এক বছরে নিজেকে অপ্রচলিত করে দেবে?"
একটি ফরোয়ার্ড সামঞ্জস্য স্তরের সাথে, এটি কখনই নিজেকে অপ্রচলিত করে তুলবে না। এটাই আসল কথা.
সমাবেশ প্রোগ্রামিং একটি পৌরাণিক কাহিনী দ্বারা আটকে আছে যে সমাবেশে লেখা কঠিন এবং তাই অবাস্তব। কুয়াশার প্রস্তাবনাটিও এই সমস্যার সমাধান করে। যদি লোকেরা মনে করে যে সমাবেশে লেখা কঠিন, এবং সি তে লেখা নয়, ঠিক আছে, আসুন কেবল অ্যাসেম্বলারটিকে সি এর মতো দেখাই। কোনও সমস্যা নেই। আধুনিক অ্যাসেম্বলি ল্যাঙ্গুয়েজ 50-এর দশকে তার পিতামহের মতো দেখতে ঠিক একই রকম হওয়ার কোনও উপযুক্ত কারণ নেই।
আপনি নিজেই তিনটি সমাবেশের নমুনা দেখেছেন। তাদের কোনটিই "ঐতিহ্যবাহী" সমাবেশের মতো দেখায় না এবং কোনওটিই হওয়া উচিত নয়৷
সুতরাং, ফরওয়ার্ডকম হল সেই সমাবেশ যেখানে আপনি সর্বোত্তম কোড লিখতে পারেন যা কখনই অপ্রচলিত হবে না এবং যা আপনাকে একটি "প্রথাগত" সমাবেশ শিখতে বাধ্য করে না। সমস্ত ব্যবহারিক বিবেচনার জন্য, এটি ভবিষ্যতের সি। C++ নয়।
আমরা একটি উত্তর-আধুনিক বিশ্বে বাস করি। মানুষ ছাড়া আর কিছুই মরে না। ঠিক যেমন ল্যাটিন প্রকৃতপক্ষে কখনই মারা যায় না, ঠিক যেমন COBOL, Algol 68, এবং Ada, - C++ জীবন এবং মৃত্যুর মধ্যে চিরন্তন অর্ধ-অস্তিত্বের জন্য ধ্বংসপ্রাপ্ত। C++ প্রকৃতপক্ষে কখনই মারা যাবে না, এটি কেবলমাত্র নতুন আরও শক্তিশালী প্রযুক্তির দ্বারা মূলধারার বাইরে ঠেলে দেওয়া হবে।
ঠিক আছে, "ধাক্কা দেওয়া হবে" নয় বরং "ধাক্কা দেওয়া হচ্ছে"। আমি একজন C++ প্রোগ্রামার হিসেবে আমার বর্তমান চাকরিতে এসেছি, এবং আজ আমার কাজের দিন পাইথন দিয়ে শুরু হয়। আমি সমীকরণগুলি লিখি, SymPy আমার জন্য সেগুলি সমাধান করে এবং তারপর সমাধানটিকে C++ এ অনুবাদ করে। তারপরে আমি এই কোডটি C++ লাইব্রেরিতে পেস্ট করি এমনকি এটিকে একটু ফরম্যাট করতেও বিরক্ত করি না, যেহেতু ঝনঝন-পরিপাটি যাইহোক আমার জন্য এটি করবে। একটি স্ট্যাটিক বিশ্লেষক পরীক্ষা করবে যে আমি নেমস্পেসগুলি এলোমেলো করিনি এবং একটি গতিশীল বিশ্লেষক মেমরি ফাঁসের জন্য পরীক্ষা করবে। CI/CD ক্রস-প্ল্যাটফর্ম সংকলনের যত্ন নেবে। একজন প্রোফাইলার আমাকে বুঝতে সাহায্য করবে যে আমার কোড আসলে কিভাবে কাজ করে, এবং ডিসসেম্বলার - কেন।
আমি যদি "C++ নয়" এর জন্য C++ ট্রেড করি, তাহলে আমার কাজের 80% ঠিক একই থাকবে। আমি যা করি তার বেশিরভাগের জন্য C++ কেবল অপ্রাসঙ্গিক। এর মানে কি আমার জন্য C++ ইতিমধ্যেই 80% মৃত?
স্থিতিশীল প্রসারণ দ্বারা বিকশিত সীসা চিত্র।