نرمافزار Matlab با توجه به دستورها و توابع ساده و محیط دادهای برداریای که در بر دارد، یکی از بهترین و کاراترین نرمافزارها برای کاربرانی است که دانش عمیقی از برنامهنویسی ندارند و نیاز دارند تا وقت و زمان خود را صرف آزمایش طرحهای جدید و پیش نمونهسازی الگوریتمهای جديد كنند. پس از معرفی CUDA و فراهم شدن امکان استفاده از قدرت GPU در محاسبات، دو ابزار مناسب برای بهرهبرداری از این تواناييها در محیط Matlab معرفی شدند و در زمینه حل مسائل سنگین ریاضی و فیزیک در شاخههای مختلف علوم از جمله مهندسی و پزشکی تحولی شگرف پدید آوردند. این ابزارها GPUmat و Jacket نام دارند که اولی ابزاری رایگان بوده و به سهولت قابل تهیه است. در نقطه مقابل، ابزار Jacket رایگان نيست و در عین حال، امکانات و قابلیتهای بسیار بهتر و مناسبتری دارد. در این مقاله به بررسی قابلیتهای معرفی شده توسط Jacket میپردازیم.
گرافیک در JACKET
همانطور
که قبلاً اشاره شد، توابع گرافیکی مناسبی برای نمایش دادههای GPU به
صورت مستقیم در Jacket در نظر گرفته شده است که در نوع خود منحصر به فرد
بوده و کاربردهای بسیار خوبی دارند. یکی از این توابع، تابع GPlot است که
برای کشیدن نمودارهای دو بعدی (همانند Plot در Matlab) بهکار ميرود.
فهرست 4 برنامهای نمونه برای استفاده از GPLOT را در بر دارد. شكل 3
خروجی این برنامه را نشان ميدهد. توجه كنيد که برای استفاده از Gplot
باید مسیر m فایل gplot در Jacket را به مسیر اجرایی Matlab اضافه كنيد.
یکی دیگر از توابعی که برای نمایش دادههای GPU در Jacket کاربرد دارد،
تابع GSURF است که کاربردی مشابه تابع SURF استاندارد دارد. این تابع یک
ماتریس دو بعدی و نرمالایز شده را بهعنوان ورودی دریافت کرده و به صورت
یک نمودار سطحی نمایش ميدهد. فهرست 5 برنامهای را برای استفاده از GSURF
ارائه ميكند. خروجی این برنامه در شكل 4 به نمایش درآمده است. به
طور کلی، ميتوان با استفاده از فرمان GFIGURE یک تصویر در فضای GPU
تولید کرده و محتوای آن را به دلخواه تعیین كرد. فرمان GFIGURE از لحاظ
کاربرد مشابه فرمان FIGURE در محیط Matlab عمل ميكند. در فهرست 6
برنامهای برای رسم یک کره چرخان با استفاده از OpenGL در فضای GPU ارائه
شده است. خروجی این برنامه را در شكل5 مشاهده ميكنيد.
A = randn( 1, 100 ); % Initialize a random vector
A = A + abs( min( A ) ); % Rescale the data to [0 1] range
A = A ./ max( A(:) );
gplot( gdouble( A ) ); % Display random image.
فهرست 4
addpath
addpath
Z = peaks( 30 ); % Generate surface data
Z = Z + abs(min( Z(:) )); % Rescale data in the [0 1] range
Z = Z ./ max( Z(:) );
gsurf( gdouble ( Z ) ); % Display the surface mesh.
فهرست 5
addpath
addpath
gfigure;
quadratic=gluNewQuadric();
gluQuadricNormals(quadratic, GLU_SMOOTH);
gluQuadricDrawStyle(quadratic,GLU_LINE);
gluQuadricTexture(quadratic, GL_TRUE);
for i=1:10000
% Do some OGL so that we see something
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0, 0.0, -6.0);
glRotatef(i/20,0,0.5,0.2);
glColor3f(1.0, 0.0, 0.0);
gluSphere(quadratic,2,32,32);
glXSwapBuffers;
end
فهرست 6

شکل 5
ارزیابی
پس
از آشنایی با مفاهیم کلی استفاده از قابلیتهای Jacket و توان پردازشی
GPU، نوبت آن ميرسد تا مزایای استفاده از پردازنده گرافیکی در محاسبات و
میزان کارایی آن را در مقابل CPU ارزیابی كنيم. برای این کار، مشابه با
آنچه در «مقاله پردازشموازی با Matlab» انجام دادهایم، در یک برنامه
تابعی برای انجام محاسبات سنگین نوشته و دو نمونه از آن را روی CPU و GPU
اجرا کرده و زمانهای اجرا را محاسبه ميكنيم. با مقایسه این زمانها،
ميتوان به دید مناسبی از کارایی GPU نسبت به CPU دست یافت. فهرست
7 یک تابع را برای انجام محاسبات سنگین روی CPU یا GPU در بر دارد.
فهرست 8 فایل استفاده کننده از این تابع را نشان ميدهد. خروجی این
برنامه مشابه آنچه در مقاله پردازش موازی با Matlab در همین شماره ارائه
شده، در فهرست 9 آورده شده است. همانطور که ميبینید، افزایش سرعت یک
پردازنده گرافیکی نسبت به یک پردازنده عادی بسیار خوب و حدود 26 برابر است.
با این حال، استفاده از دو پردازنده گرافیکی باعث شده تا سرعت محاسبات
کاهش یابد. به اين دلیل که این برنامه روی سیستمی اجرا شده است که از دو
کارت گرافیک 9400 و 9600 شرکت nVIDIA بهره ميبرده است.
function [ T ] = multibenchNLN( Ain, E )
%multibenchNLN Benchmark based on use of non-linear processing.
%% SET UP VARIABLES
Msz = size(Ain,1);
if strcmp(class(Ain),›gsingle›), % If GPU, predefine GPU variables
a = gzeros(Msz,1,›single›);
R = gzeros(Msz,1,›single›);
k1 = gsingle(pi/4);
k2 = gsingle(pi/5);
A = gsingle(Ain);
geval(a,R,k1,k2,A);
else % If CPU, predefine CPU variables
a = zeros(Msz,1,›single›);
R = zeros(Msz,1,›single›);
k1 = single(pi/4);
k2 = single(pi/5);
A = single(Ain);
end
%% PERFORM COMPUTATIONS - HERE ONLY THE EXECUTION TIME IS PASSED BACK
gsync;
tstart = tic;
parfor e=1:E
a = A(:,e); % Extract vector from matrix data
R = k2*a - k1.^2*a.^2 ...
+ k2.^2*a.^3 - k1.^3*a.^4 ...
+ k2.^4*a.^5 - k1.^5*a.^6 ...
+ k2.^7*a.^7 - k1.^8*a.^8 ...
+ k2.^9*a.^9 - k1.^10*a.^10 ...
+ k2.^11*a.^11 - k1.^12*a.^12 ...
+ k2.^13*a.^13 - k1.^14*a.^14 ...
+ k2.^15*a.^15 - k1.^16*a.^16 ...
+ k2.^17*a.^17 - k1.^18*a.^18 ...
+ k2.^19*a.^19 - k1.^20*a.^20;
geval(a,R); % Force computations - does no harm for CPU
end
gsync;
T = toc(tstart);
end
فهرست 7
%% multibench - benchmarking script to test Jacket with PCT
clear all;
NLNcols = 2^20;
% Number of frames
E = 16;
% Set number of workers
noWorkers = 2;
% Create reference matrix
Aref = rand(NLNcols,E);
%% SINGLE WORKER CPU
if matlabpool(‘size’) > 0
matlabpool close force;
end
% Input matrix
A = Aref;
% Define CPU variables
[~] = multibenchNLN( A, 4 );
[~] = multibenchNLN( A, 4 );
T_single_CPU = multibenchNLN( A, E );
%% SINGLE WORKER GPU
% Input matrix
A = gsingle(Aref);
% Define GPU variables
[~] = multibenchNLN( A, 4 );
[~] = multibenchNLN( A, 4 );
T_single_GPU = multibenchNLN( A, E );
%% MULTI WORKER CPU
isOpenCorr = matlabpool(‘size’) == noWorkers;
if ~isOpenCorr,
matlabpool close force
matlabpool(noWorkers)
end
% Input matrix
A = Aref;
% Define CPU variables
[~] = multibenchNLN( A, 4 );
[~] = multibenchNLN( A, 4 );
T_multi_CPU = multibenchNLN( A, E );
%% MULTI WORKER GPU
% Reference matrix
A = gsingle(Aref);
% Perform test and clear reference matrices
[~] = multibenchNLN( A, E );
[~] = multibenchNLN( A, E );
T_multi_GPU = multibenchNLN( A, E );
clear Aref;
%% PRINT DATA
fprintf(‘=============================================\n’);
strCPU1 = ‘# Workers: %d -> CPU Time [s]: %8.3f\n’;
fprintf(strCPU1, 1, T_single_CPU);
strGPU1 = ‘# Workers: %d -> GPU Time [s]: %8.3f\n’;
fprintf(strGPU1, 1, T_single_GPU);
strCPU1 = ‘# Workers: %d -> CPU Time [s]: %8.3f\n’;
fprintf(strCPU1, noWorkers, T_multi_CPU);
strGPU1 = ‘# Workers: %d -> GPU Time [s]: %8.3f\n’;
fprintf(strGPU1, noWorkers, T_multi_GPU);
str = ‘Speed-up; 1-CPU / M-CPU [-]: %8.3f\n’;
fprintf(str, T_single_CPU/T_multi_CPU);
str = ‘Speed-up; 1-GPU / M-GPU [-]: %8.3f\n’;
fprintf(str, T_single_GPU/T_multi_GPU);
str = ‘Speed-up; 1-GPU / 1-CPU [-]: %8.3f\n’;
fprintf(str, T_single_CPU/T_single_GPU);
str = ‘Speed-up; M-GPU / M-CPU [-]: %8.3f\n’;
fprintf(str, T_multi_CPU/T_multi_GPU);
fprintf(‘=============================================\n’);
فهرست 8
>> multibench
Did not find any pre-existing parallel jobs created by matlabpool.
Starting matlabpool using the ‹local› configuration ... connected to 2 labs.
=============================================
# Workers: 1 -> CPU Time [s]: 58.992
# Workers: 1 -> GPU Time [s]: 2.245
# Workers: 2 -> CPU Time [s]: 30.837
# Workers: 2 -> GPU Time [s]: 2.374
Speed-up; 1-CPU / M-CPU [-]: 1.913
Speed-up; 1-GPU / M-GPU [-]: 0.946
Speed-up; 1-GPU / 1-CPU [-]: 26.278
Speed-up; M-GPU / M-CPU [-]: 12.989
=============================================
>>
فهرست 9
با
اینکه قدرت پردازشی کارت 9600M چیزی حدود دو برابر کارت 9400M است، اما
تقسیم مساوی و 50,50 دادهها و پردازش بر روی این دو منجر به کاهش سرعت
پردازش شده است. برای دستیابی به سرعت بالاتر و مناسبتر هنگام استفاده از
چند پردازندهگرافیکی، روشهای مختلفی وجود دارد که برای مطالعه بیشتر
ميتوانيد بخش «منابع و مأخذ» را مشاهده كنيد.
جمعبندی
در
مقاله حاضر به معرفی یک ابزار مناسب و سودمند در رابطه با استفاده از
قدرت پردازشی GPU در محیط کاربر پسند و ساده نرمافزار Matlab که یکی از
پرکاربردترین نرمافزارها در حوزه محاسبات علمی، فنی و مهندسی است،
پرداختیم. این ابزار قابلیتهای
خوبی درباره تبدیل و انتقال دادهها روی GPU و نمایش دادههای GPU بهصورت
مستقیم داشته و با فراهمسازی امکاناتی چون کامپایلر اختصاصی برای تولید
فایلهای اجرایی مستقل از Matlab انعطاف بسیار بالایی برای کاربران خود به ارمغان ميآورد.
برچسبها: حل یک معادله غیر تحلیلی با متلب, پیاده سازی الگوریتم SPID4, 7 با matlab, 7 با مت لب
