سلام؛ سعی کردم توی این نوشته، بخش های مهم ارائه Concurrency is not parallelism که توسط Rob Pike رو یه جورایی ترجمه کنم. و خوشحال میشم اگر مشکلی توی متن یا ترجمه بود کامنت بزارید تا تصحیح اش کنم.
این ارائه نسبتا طولانیه پس قراره چند تا پارت داشته باشیم و میتونید لینک پارت های قبلی و بعدی رو در انتهای نوشته پیدا کنید.
و اسلاید های ارائه رو هم میتونید از اینجا ببینید.
خب فرض کنیم میخوایم از دست این کتابای قدیمی خلاص بشیم. پس یه gopher داریم که اونا رو میبره و میندازه داخل زباله سوز. (اینجا Rob Pike یه اشاره هایی به کتابای ++C میکنه?) ولی خب ما فقط یه gopher داریم پس زمان خیلی زیادی طول میکشه این کار تموم بشه مخصوصا اگر تعداد کتاب هامون زیاد باشن.
خب اگه ما یه gopher دیگه بیاریم و بهش گاری بدیم چی؟ کار سریعتر انجام میشه. ولی اینجا یه مشکلی هست. اونها میتونند سر راه همدیگه قرار بگیرند. و جلوی زباله سوز یا جایی که کتاب هارو برمیدارند گیر بیافتند، پس لازمه که اونها هماهنگ بشند. پس اونها باید باهم ارتباط برقرار کنند مثل ارسال کردن یه پیام به همدیگه یا...
خب اگه همه چیز رو دو برابر کنیم چی؟ gopher ها، زباله سوز ها، گاری ها و حتی تعداد کتاب ها. حالا ما توی همون زمان دو برابر تعداد کتاب جابجا میکنیم و میسوزونیم. ( دو برابر زمانی که فقط یک gopher داشتیم). درسته این میشه parallel. ولی به این فکر کنید که ترکیب concurrent این دو gopher هست که این کارو انجام میده.
این طراحی به صورت خودکار parallel نیست. میدونیم که دوتا gopher وجود داره. ولی کی گفته که هر دوتاشون همزمان کار میکنند؟ من میتونم بگم که فقط یک gopher اجازه حرکت در لحظه رو داره. دقیقا مثل داشتن یک کامپیوتر تک هسته ای (core). اونوقت طراحی همچنان concurrent و درسته. اما ذاتا دیگه parallel نیست. مگر اینکه بتونیم هر دوی این gopher هارو همزمان در لحظه حرکت بدیم. اینجاست که parallelism میاد وسط. یعنی اجرای همزمان دو چیز، نه صرفا داشتن دو چیز.
خب ما دیدیم که میتونیم مشکل رو به قطعات concurrent تقسیم کنیم. پس میتونیم مدل های دیگه ای هم ارائه کنیم.
حالا ما همونقدر کتاب داریم با همون یدونه زباله سوز، ولی اینبار ۳ تا gopher داریم که باید زحمت کارای مارو بکشن. یکیشون فقط کتاب بار میزنه، یکیشون حمل میکنه و گاری خالی رو بر میگردونه، و یکی هم کتابا رو میندازه تو آتیش. که باعث میشه کارامون سریعتر انجام بشن ولی شایدم نه اونقدر سریع. چون ممکنه متوقف بشن. مثل وقتی که gopher وسطی داره با گاری خالی برمیگرده. در واقع اون لحظه کار جلو نمیره و میشه گفت هیچ کار مفیدی انجام نمیشه.
پس میتونیم یه gopher دیگه اضافه کنیم که گاری خالی رو برگردونه. یعنی حالا ۴ تا gopher داریم که هرکدوم یه کار ساده رو انجام میدن. درسته که در اصل تعداد کار های ما بیشتر شده، ولی در عوض سرعت بیشتری داریم. چون ترکیب concurrent قطعات درست مدیریت شده، سریعتر اجرا میشن.
تصور کنید همه چیز درست کار کنه و هر ۴ gopher ما مشغول کار باشند، اینجوری کار ما ۴ برابر سریع تر از ورژن اصلی که اول آورده شد پیش میره. کمی بعیده ولی ممکنه!
ما عملکرد رو با اضافه کردن یک رویه concurrent به طراحی موجود بهبود دادیم.
در واقع تعداد task هارو افزایش دادیم ولی در نهایت همه چیز (کل برنامه) سریعتر اجرا شد!
گوفرهای بیشتری که کار بیشتری انجام می دهند باعث میشود که کار سریعتر تمام شود. این بینشی عمیق تر از parallelism صرف است.
ما تونستیم مشکل رو حل کنیم و کار رو تقسیم به چندین رویه مستقل تبدیل کنیم پس حالا ما میتونیم اونها رو به صورت parallel ترکیب کنیم تا یه راه حل نهایی و بهتر بسازیم. در واقع طراحی concurrent ساختار، این موضوع رو برامون آسون تر کرده.
البته خب شایدم خبری از parallelization نباشه! ماجرا مثل قبله. کی گفته که همه ی این ۸ تا gopher در یک لحظه مشغول به کارن؟ ممکنه فقط یکیشون مشغول کار باشه. (همون ماجرای کامپیوتر تک هسته و اینا...) و ۷ تای باقی توی اون لحظه بیکار باشن.
ولی طراحی ما هنوز درسته! و این خیلی موضوع بزرگ و مهمیه. چون وقتی که در حال اجرای concurrency هستیم نیاز نیست نگران parallelism باشیم. در واقع parallelism موضوع آزادیه که ما میتونیم تصمیم بگیریم که در لحظه چند تا از این gopher های بدبخت مشغول کار باشند.
بریم سراغ یه دیزاین دیگه D:
بازم ۲ تا gopher داریم. ولی این بار به جای اینکه یه gopher کل مسیر رو طی کنه، یه ایستگاه این وسط داریم. اولیه کتابا رو بار میزنه و میاره میریزتشون وسط، و اون یکی منتظر اومدن کتابا میشه و بعدش اونا رو بار میزنه و میبره میسوزونه.
اگه سیستم درست اجرا شده باشه، در اصل ۲ برابر سریعتر از ورژن اصلی کار میکنه. حتی اگر از نظر طراحی کاملا متفاوت با طرح اصلی باشه.
واضحه که میتونیم که این طرحو parallelize کنیم. یعنی ۴ تا gopher داریم و معنیش اینه که توان عملیاتیمون ۴ برابر طرح اصلیه.
بریم سراغ طرح تقریبا آخر?
میایم به اون روش بالاییه که از ۴ تا gopher استفاده میکردیم، یه ایستگاه اضافه میکنیم. و حالا ۸ تا gopher داریم که عین جت دارن کتاب میسوزونن?
و مثل همیشه این کافی نیست و ما میتونیم با parallelize کردنش کاملش کنیم. که در واقع از همه ی تکنیک ها و دیزاین ها استفاده شده و ۱۶ تا gopher بیچاره داریم که به سختی کار میکنن :)
شما نباید به اجرای parallel برنامه فکر کنید. انتظار من این هست که شما به این فکر کنید که چطور یه مسئله رو تقسیم کنید به اجزای مستقل از هم، و بعد یه راه حل کامل براش پیدا کنید.
مثال هایی که تا الان زده شده توی دنیای واقعی نبودن، ولی اصولا میشه اونا شبیه دنیای واقعی دونست:
توی پارت بعدی قراره در مورد concurrency توی go بنویسم و به صورت ساده یاد بدم. پس از دستش ندین ؛)