اگر در حال انجام محاسبات سنگین هستید حتما متوجه شده اید که تغییر دادن الگوریتم یا زبان می تواند تاثیر زیادی در سرعت داشته باشد. اینجا می خواهیم یکی از بهترین راهها برای افزایش سرعت را ببینیم: استفاده از کارت گرافیک!
کارت گرافیک یا GPU معمولا برای بازی ها مورد استفاده قرار می گیرد اما دلیل این موضوع خودش توانایی بسیار بالای GPU در موازی سازی محاسبات است. در مورد بازی ها که معمولا دارای موتور های فیزیک هستند این توانایی بسیار مهم است چرا که بیشتر محاسبات فیزیک در جبر خطی هستند که بیشتر آن ها قابلیت موازی سازی بسیار بالایی دارند. از ضرب ماتریس ها گرفته تا معکوس گیری و غیره بر روی GPU بسیار سریع تر قابل اجرا هستند.
در چند سال اخیر با رشد انفجار گونه یادگیری ماشین در حوزه یادگیری عمیق (deep learning) شاهد توسعه ده ها چارچوب نرم افزاری شده ایم که از توانایی بالای GPU در محاسبات شبکه های عصبی استفاده می کنند. طوری که حتی سازندگان آن ها که بزرگترین بازیگر آن NVIDIA است وارد معرکه شده و به شرکت های بزرگ کمک می کنند و interface های ساده تر یا customizable برای فقط محاسبات یادگیری عمیق ارایه کرده اند.
در این جا بحثم بر روی یادگیری عمیق نیست فقط می خواهم نشان دهم که چقدر تغییر سرعت بر روی یک محاسبه ساده ضرب دو ماتریس ۱۰۰۰۰ در ۱۰۰۰۰ خواهیم داشت. برای این منظور من چهار چارچوب را مورد آزمایش قرار می دهم.
یک کتابخانه با الهام از متلب برای ایجاد چارچوبی برای محاسبات عددی مانند ضرب ماتریس هاست که در پایتون و سی پیاده سازی شده است. به صورت داخلی هم متلب و هم نامپای از BLAS و LAPACK برای محاسبات جبر خطی خود استفاده می کنند. هر دوی این کتابخانه ها بسیار سطح پایین تر هستند و دارای امکاناتی برای استفاده از ویژگی های ماشین مورد استفاده (مانند استفاده از محاسبات سریع floating point) برای سرعت بخشیدن هستند. نامپای اساسا بر روی CPU کار می کند.
کوپای یک کتابخانه فوق العاده با الهام از نامپای بر روی GPU است. هدف cupy ایجاد دقیقا همان اینترفیس اما با محاسباتی است که بر روی GPU اجرا می شوند. این کتابخانه با بهره گیری از کتابخانه های CUDA مثل cuBLAS ، cuSolve، cuDNN و غیره سرعت محاسبات را بسیار بالا برده و همه آن ها را بر روی GPU اجرا می کند.
تنسرفلو بزرگترین کتابخانه نرم افزاری برای یادگیری عمیق است که توسط گوگل توسعه می یابد. تنسرفلو ۲ که چندی پیش منتشر شد دارای اینترفیس بسیار تمیز تری است و ویژگی های زیادی هم به آن اضافه شده است. یکی از مهمترین ویژگی های تنسرفلو قابلیت اسکیل بالای آن است به این معنا که از یک موبایل تا خوشه ای از سرور ها می توانند آن ها به صورت بهینه اجرا کنند و از تمام منابع به خوبی استفاده می کند. قابلیت دیگر تنسرفلو بهره گیری اش از TPU یا Tensor Processing Unit است که حتی بیشتر از GPU سرعت محاسبات را بالا میبرد.
یک کتابخانه دیگر برای یادگیری عمیق که بر اساس torch است. این کتابخانه توسط facebook در حال توسعه و گسترش است و از قابلیت GPU می تواند استفاده کند.
در اینجا فقط به یک محاسبه ماتریسی اکتفا می کنیم که قطعا یک بنچ مارک کامل نیست اما ایده ای کلی به شما می دهد. برای این منظور شما باید یک کارت گرافیک Nvidia همراه با CUDA بر روی سیستم خود نصب داشته باشید. اگر ندارید یا تنظیمات آن برای شما سخت است می توانید از کولب گوگل استفاده کنید. کافی است به اکانت گوگل خود لاگین کنید و شروع به کد زدن کنید. بدون هیچ تنظیمات و پیکر بندی!
صد البته استفاده از کولب باعث می شود محاسبات به نفع tensorflow بچرخد چون سرور ها و تنظیمات آن ها برای این کتابخانه تنظیم شده است اما می توانید ببینید که چقدر تفاوت بین استفاده از GPU در موارد CuPy ، Pytorch و Tensorflow نسبت به محاسبه توسط Numpy وجود دارد. برای این منظور میتوانید Colab من را ببنید. نتایج به صورت زیر هستند.
۱- نامپای: ۷۰.۴۴ ثانیه
۲- تنسرفلو: 0.00034 ثانیه
۳- کوپای: 0.00289 ثانیه
۴- پای تورچ:0.00571 ثانیه
همانطور که می بینید برنده مشخص این بازی تنسرفلو است.
اما برای محاسبات دقیق تر بین سه رقیب اصلی همین کار را (ضرب دو ماتریس بزرگ ۱۰۰۰۰ در ۱۰۰۰۰) برای ۱۰۰ بار انجام میدهیم. نتایج:
۱- تنسرفلو: ۰.۹۷۹۰ ثانیه
۲- کوپای: ۱۰.۷۵ ثانیه
۳- پایتورچ: ۵.۲۰۴ ثانیه
اینجاست که کاملا مشخص می شود کولب قطعا برای کار با تنسرفلو تغییر کرده است. چون در بسیاری از بنچ مارکها تفاوت تنسرفلو و پایتورچ بسیار اندک است. اگر بر روی کامپیوتر خودتان این کار را انجام دهید متوجه می شوید که اختلاف بسیار جزیی است. نتیجه اخلاقی اینکه اگر از colab استفاده می کنید بهتر است از tensorflow استفاده کنید.
متلب تنها رقیبی است که به صورت مستقیم قابل مقایسه نیست چون نمی توان آن را بر روی colab اجرا کرد. اما نسخه های جدیدتر متلب با استفاده از gpuArray این امکان را می دهند که محاسبات را بر روی gpu اجرا کرد.
خوبی متلب مثل همیشه سینتکس ساده آن است. سرعت اجرای محاسبات بر روی GPU بر روی کامپیوتر من در cupy و متلب تقریبا برابر بودند. اما مشکلی که من متوجه آن شدم این است که متلب محاسبات را در حافظه GPU نگه می دارد تا زمانی که شما آن را با دستور gather به حافظه اصلی برگردانید. این دستور بسیار کند و هزینه بر است. از طرفی تمام کتابخانه های بالا به شما امکان دیدن خروجی ها را بدون برگرداندن به حافظه اصلی را می دهند که امکان بسیار خوبی برای دیباگ کردن است. اگرچه نسخه های قبلی tensorflow این ویژگی را نداشتند اما با اضافه کردن eager execution به صورت دیفالت می توان مقادیر تمامی متغیر ها را در زمان اجرا و دیباگ دید.
این پست به هیچ وجه یک مقایسه دقیق و جامع نیست. نکات بسیار ظریفی در بنچ مارک ها وجود دارد که باید مورد مقایسه قرار بگیرند. اما می توان چند نتیجه گیری کلی انجام داد:
۱- استفاده از GPU سرعت محاسبات را در اوردر ده تا صد برابر افزایش می دهند.
۲- تنسرفلو بر روی colab سریع ترین کتابخانه محاسبات است.
۳- متلب رقیب خوبی برای محاسبات است اما ابزارهای دیباگ کردن آن قدیمی و در کار واقعی بسیار دردسر ساز است.