ضرب ماتریس به صورت موازی
معرفی
میخواهیم ضرب دو ماتریس را به روش سری و همچنین سه روش موازی انجام دهیم و نتیجه را مقایسه کنیم:
- Open-MP
- MPI
- CUDA
در اینجا هدف آموزش یا معرفی سه روش فوق نیست. فرض بر این است که شما با برنامهنویسی با سه روش فوق آشنا هستید. در اینجا هدف کامپایل و اجرای برنامه نوشته شده در لینوکس است. دستورات زیر بر روی توزیع Debian 8.6 و Mint 18 اجرا و تست شدهاند.
Serial
حالت سریال کدنویسی و کامپایل و اجرای بسیار ساده و روتینی دارد. کافیست کامپایلر gcc را نصب داشته باشید. اگر کد خود را در فایلی به نام serial.cpp نوشتهاید کافیست با دستور زیر آن را کامپایل کنید:
g++ serial.cpp -o serial
چنانچه کامپایل با موفقیت اتجام شد فایل باینری serial ساخته میشود که به راحتی قابل اجراست:
./serial
Open-MP
در این روش همان برنامه سریال را با اندک تغییر میتوان موازی کرد. برای اینکار از کامپایلر دایرکتیوهای open-mp استفاده میکنیم.
برای کامپایل کافیست پارامتر openmp را به خط فرمان کامپایلر اضافه کنیم. مثلا اگر نام فایل حاوی سورس omp.cpp باشد با این دستور میتوان آن را کامپایل و لینک کرد:
g++ -openmp omp.cpp -o omp-mp
./omp
MPI
برنامه MPI هم نحوه کامپایل متفاوتی دارد و هم نحوه اجرای آن فرق دارد. برای کامپایل باید بسته mpi-default-dev نصب باشد و با دستور mpicc یا mpic++ برنامه کامپایل شود:
sudo apt-get install mpi-default-dev
mpic++ mpi.cpp -o mpi
برای اجرا باید بسته mpi-default-bin نصب باشد و با دستور mpirun برنامه اجرا شود:
apt-get install mpi-default-bin
mpirun -n 4 ./mpi
در این مثال تعداد پردازندهها ۴ است.
برای داشتن شرایط واقعی بایستی به صورت توزیع شده با چند تا سیستم برنامه اجرا شود. برای اینکار فایل باینری را بر روی همه کلاینتها ایجاد کنید. اگر مشخصات کلاینتها با سرور یکی است، از همان فایل باینری سرور میتوانید استفاده کنید. وگر نه باید در هر کلاینت با دستور mpic++ فایل باینری مخصوص به خود را درست کنید.
برای سهولت مسیر فایل باینری روی سرور با همه کلاینتها یکسان باشد. مثلا اگر روی سرور فایل اجرایی در مسیر
/home/mt/matrix/mpi
قرار دارد، فایل اجرایی با همین نام mpi روی همه کلاینتها در همین مسیر قرار گیرد.
همچنین نام کاربری مورد استفاده روی سرور، بر روی همه کلاینتها ایجاد شود و ضمنا با کپی کلید عمومی سرور بر روی کلاینتها اجازه لاگین ssh از سرور به کلاینتها را بدهید. برای درست کردن یک کلید عمومی/خصوصی از دستور
ssh-keygen -t rsa
استفاده کنید. سپس برای کپی کلید عمومی سرور بر روی هر کلاینت دستور زیر را در سرور اجرا کنید:
ssh-copy-id user@client
که در آن user نام کاربری و client آیپی کلاینت است.
اکنون آیپی کلاینتها را در فایلی به اسم مثلا hostfile بنویسید (در هر خط یک آی پی). آخرین مرحله اجرای فایل mpi است به طوری که با پارامتر hostfile اسم فایل حاوی آیپی کلاینتها را به آن معرفی کردهاید:
mpirun --hostfile hostfile ./mpi
MPI on ARM
برای اجرا بر روی اندروید میتوان از نرم افزار termux استفاده کرد. با کمک این نرم افزار میتوانید دستورات را بر روی لینوکس گوشی خود اجرا کنید. همچنین بسیاری از پکیجها را بر روی مخازن خود برای ARM آماده کرده است.
ولی متاسفانه پکیجهای mpi وجود ندارد. برای کامپایل mpi از روی سورس پس از نصب gcc و دانلود سورس mpi فایل configure باید اجرا شود که با خطا مواجه میشود. اولا باید /bin/sh و /bin/rm و ... به /system/bin/sh و /system/bin/rm و ... تغییر پیدا کند. ثانیا از انجایی که از مجوز نوشتن در مسیر tmp خطا میگیرد، با کمک لینک
Problems with here docs/strings in Android implementations of bash/mksh
مسیر tmp اصلاح شد:
export TMPDIR=/sdcard/.tmp/$RANDOM
mkdir -p $TMPDIR
سپس باید configure اجرا شود
./configure --build=arm-linux-gnueabi --host=armv7-linux-gnueabi \
--disable-mpi-fortran \
--disable-mpi-cxx --prefix=`pwd`/install \
--enable-shared --enable-static \
--disable-mmap-shmem --disable-posix-shmem --disable-sysv-shmem \
--disable-dlopen
ولی خطا گرفت و کار نکرد!
checking host system type... Invalid configuration `armv7-linux-gnueabi': machine `armv7' not recognized
configure: error: /data/data/com.termux/files/usr/bin/sh config/config.sub armv7-linux-gnueabi fa
برای همین تصمیم گرفتم cross compiling انجام بدم. با کمک لینک
Cross compile for ARM
دو بسته g++-arm-linux-gnueabi و binutils-arm-linux-gnueabi را نصب کردم:
sudo apt install g++-arm-linux-gnueabi
ولی هنوز به نتیجه نرسیدهام!
CUDA
استفاده از GPU برای کارهای محاسباتی و به طور کلی غیر از گرافیکی که بناست خروجی کار به حافظه سیستم برگردد را GPGPU (General Purpose GPU) میگویند. برای اینکار اولا باید درایور کارت گرافیک برای GPGPU نصب باشد. ثانیا ابزار نرم افزاری کار شامل کامپایلر را نصب کنید.
در این سایت مراحل کار برای نصب CUDA توضیح داده شده است:
http://matrivian.github.io/linux/2016/04/28/Install-Cuda.html
download cuda-repo-ubuntu1604-8-0-local_8.0.44-1_amd64-deb (1.9 GB by using VPN)
sudo dpkg -i cuda-repo-ubuntu1604-8-0-local_8.0.44-1_amd64-deb
sudo apt-update
sudo apt install cuda