هدف از کد بالا نشان دادن تاثیر پیشتخصیص (preallocation) در افزایش سرعت کد است. کد اول 40000 جمله اول از دنباله فیبوناچی را تولید میکند، در صورتی که بردار Fibonacci بصورت دینامیکی در حال رشد است. با تغییر اندازه این بردار پردازنده مدام به حافظه (ram) سر میزند و یک بلوک متناسب با آن را تخصیص میدهد. این سر زدن متوالی به حافظه باعث کند شدن برنامه میشود. در حالی که در برنامه دوم با پیشتخصیص توانستهایم سرعت برنامه را 9 برابر (این عدد از یک سیستم به سیستم دیگر ممکن است تغییر کند) سریعتر کنیم.
@MatlabTips
@MatlabTips
#SpeedUp
پیش نیاز: آشنایی مقدماتی با کدنویسی در MATLAB
@MatlabTips
بردارها و ماتریسها قلب هر برنامه MATLAB را تشکیل میدهند. هنگامی که عملیات MATLAB بصورت برداری و ماتریسی انجام شود، عملکرد آن به شدت بهینه میشود. "برداریسازی" هنر تبدیل محاسبات بصورت عنصر به عنصر (همانگونه که در حلقهها میبینیم) به عملیاتی برداری است.
با یک مثال ساده شروع میکنیم:
1⃣فرض کنید دو ماتریس A و B و هم اندازه داریم. دو روش برای ضرب آنها وجود دارد: ✔️عنصر به عنصر
✔️یا بصورت برداری عناصر آن را با عملگر ضرب آرایهای در هم ضرب کنیم.
@MatlabTips
یک مثال دیگر:
2⃣فرض کنید میخواهیم تمام حجمهای ممکن برای استوانههایی با شعاع R و ارتفاع H رامحاسبه کنیم.
✔️روش عنصر به عنصر:
✔️روش برداری:
@MatlabTips
پیش نیاز: آشنایی مقدماتی با کدنویسی در MATLAB
@MatlabTips
بردارها و ماتریسها قلب هر برنامه MATLAB را تشکیل میدهند. هنگامی که عملیات MATLAB بصورت برداری و ماتریسی انجام شود، عملکرد آن به شدت بهینه میشود. "برداریسازی" هنر تبدیل محاسبات بصورت عنصر به عنصر (همانگونه که در حلقهها میبینیم) به عملیاتی برداری است.
با یک مثال ساده شروع میکنیم:
1⃣فرض کنید دو ماتریس A و B و هم اندازه داریم. دو روش برای ضرب آنها وجود دارد: ✔️عنصر به عنصر
A=rand(100,1);
B=rand(100,1);
for i=1:100
C(i)=A(i)*B(i);
end
✔️یا بصورت برداری عناصر آن را با عملگر ضرب آرایهای در هم ضرب کنیم.
A=rand(100,1);
B=rand(100,1);
C=A.*B;
@MatlabTips
یک مثال دیگر:
2⃣فرض کنید میخواهیم تمام حجمهای ممکن برای استوانههایی با شعاع R و ارتفاع H رامحاسبه کنیم.
✔️روش عنصر به عنصر:
R = 1:10000; %radious
H = 1:400; %Height
V = zeros(10000,4000); %preallocate V(volume) to speed up
for i = 1:numel(H)
for j = 1:numel(R)
V(j,i) = pi * R(j).^2 * H(i);
end
end
✔️روش برداری:
R = 1:10000;
H = 1:400;
[matR, matH] = meshgrid(R,H);
V = pi.*matR.^2.*matH;
@MatlabTips
%@MatlabTips
% Using a loop(element by element)
tic
R = 1:10000; %radious
H = 1:400; %Height
V = zeros(10000,4000); %preallocate V(volume) to speed up
for i = 1:numel(H)
for j = 1:numel(R)
V(j,i) = pi * R(j).^2 * H(i);
end
end
toc
clear all
%@MatlabTips
% Vectorized code , 6x faster in my machine
tic
R = 1:10000;
H = 1:400;
[matR, matH] = meshgrid(R,H);
V = pi.*matR.^2.*matH;
toc
✔️کدهای مربوط به مثال بالا و مقایسه سرعت آن ها
🔵تجاربی از کاربا MATLAB که سال ها طول می کشد یاد بگیرید🔵
(پیش نیاز: بدون پیش نیاز)
@MatlabTips
این نکات با این که در نگاه اول ساده به نظر می رسند، در دراز مدت اگر با آنها آشنایی نداشته باشید شما را با زحمت روبرو می کنند و لذت کد زدن با MATLAB را به سختی تبدیل میکند.
1⃣ اعداد اعشاری را درست بنویسید:
این نکته شاید ساده به نظر برسد ولی وقتی چند صد خط کد متلب بنویسید و این نکته ساده را فراموش کنید پیدا کردن خطا مثل پیدا کردن سوزن در انبار کاه به نظر می رسد. خیلی ساده است که .5 را با 5. اشتباه بگیرید و یافتن آن میان آن همه کد کار سختی است. پس بهتر است از اول خودتان را عادت بدهید به جای 5. بنویسید: 0.5
2⃣ از توابع و اسامی خود متلب برای نام گذاریی کدهایتان استفاده نکنید:
متاسفانه MATLAB زبان بسیار آسان گیری است و اگر از اسامی تابع هایش برای تابع های خودتان استفاده کنید اشکالی نمی گیرد. اما همین ممکن است به مشکلاتی منجر شود که حل کردنشان بسیار دشواراست چون برنامه تان را می نویسید و با هیچ خطایی مواجه نمی شوید اما نتایجتان را نمی گیرید! مثلا وقتی از کلماتی مانند ans ، filter، mean استفاده کنید به مشکل بر میخورید. برای اینکه مطمئن شوید اسم تابع تان قبلا درMATLAB ثبت نشده کافیست در خط فرمان متلب بنویسید:
که در آن myname اسم تابع یا متغیر شماست. اگر قبلا در متلب این اسم ثبت نشده باشد با خطای
روبرو می شوید که به این معنی است که شما آزادید از آن نام استفاده کنید در غیر این صورت بهتر است اسم دیگری انتخاب کنید.
3⃣ تا جایی که می توانید از فاصله و semicolonاستفاده کنید:
کدی که بخش بندی شده و از فاصله بین متغیرها و عملگر ها استفاده می کند راحتتر قابل خواندن است و دیرتر از کد زدن خسته یا زده می شوید. پس سعی کنید تا جایی که می توانید تمیز بنویسید.
@MatlabTips
4⃣ اسم های با مسما برای متغیر هایتان استفاده کنید:
اگر از اسم های با معنی تری در کد هایتان استفاده کنید خواندن دوباره کدها برایتان ساده تر می شود. بنابراین از اسم های ناشیانه ای مثل aaa، temp، r1 وغیره که فقط باعث سردرگمی بیشتر می شوند خودداری کنید. اسم هایی مثل centroidX ، fidCurrentFile و غیره بسیار مناسب تر هستند. اگر برای اسمی به نظرتان نمی رسد احتمالا آن قسمت از کد را درست متوجه نشده اید! فراموش نکنید که برنامه نویسی فراتر از خروجی گرفتن است، کدهای شما می بایست مانند یک داستان روایت مناسبی از آنچه الگوریتم انجام می دهد باشد: بسیار شبیه به آنچه برای دوستتان تعریف می کنید.
✔️ به نمونه کد های زیر دقت کنید و هر دو یک کار را انجام می دهند اما...
(A-2)
(ادامه دارد)
(پیش نیاز: بدون پیش نیاز)
@MatlabTips
این نکات با این که در نگاه اول ساده به نظر می رسند، در دراز مدت اگر با آنها آشنایی نداشته باشید شما را با زحمت روبرو می کنند و لذت کد زدن با MATLAB را به سختی تبدیل میکند.
1⃣ اعداد اعشاری را درست بنویسید:
این نکته شاید ساده به نظر برسد ولی وقتی چند صد خط کد متلب بنویسید و این نکته ساده را فراموش کنید پیدا کردن خطا مثل پیدا کردن سوزن در انبار کاه به نظر می رسد. خیلی ساده است که .5 را با 5. اشتباه بگیرید و یافتن آن میان آن همه کد کار سختی است. پس بهتر است از اول خودتان را عادت بدهید به جای 5. بنویسید: 0.5
2⃣ از توابع و اسامی خود متلب برای نام گذاریی کدهایتان استفاده نکنید:
متاسفانه MATLAB زبان بسیار آسان گیری است و اگر از اسامی تابع هایش برای تابع های خودتان استفاده کنید اشکالی نمی گیرد. اما همین ممکن است به مشکلاتی منجر شود که حل کردنشان بسیار دشواراست چون برنامه تان را می نویسید و با هیچ خطایی مواجه نمی شوید اما نتایجتان را نمی گیرید! مثلا وقتی از کلماتی مانند ans ، filter، mean استفاده کنید به مشکل بر میخورید. برای اینکه مطمئن شوید اسم تابع تان قبلا درMATLAB ثبت نشده کافیست در خط فرمان متلب بنویسید:
»which myname
که در آن myname اسم تابع یا متغیر شماست. اگر قبلا در متلب این اسم ثبت نشده باشد با خطای
‘myname’ not found.
روبرو می شوید که به این معنی است که شما آزادید از آن نام استفاده کنید در غیر این صورت بهتر است اسم دیگری انتخاب کنید.
3⃣ تا جایی که می توانید از فاصله و semicolonاستفاده کنید:
کدی که بخش بندی شده و از فاصله بین متغیرها و عملگر ها استفاده می کند راحتتر قابل خواندن است و دیرتر از کد زدن خسته یا زده می شوید. پس سعی کنید تا جایی که می توانید تمیز بنویسید.
@MatlabTips
4⃣ اسم های با مسما برای متغیر هایتان استفاده کنید:
اگر از اسم های با معنی تری در کد هایتان استفاده کنید خواندن دوباره کدها برایتان ساده تر می شود. بنابراین از اسم های ناشیانه ای مثل aaa، temp، r1 وغیره که فقط باعث سردرگمی بیشتر می شوند خودداری کنید. اسم هایی مثل centroidX ، fidCurrentFile و غیره بسیار مناسب تر هستند. اگر برای اسمی به نظرتان نمی رسد احتمالا آن قسمت از کد را درست متوجه نشده اید! فراموش نکنید که برنامه نویسی فراتر از خروجی گرفتن است، کدهای شما می بایست مانند یک داستان روایت مناسبی از آنچه الگوریتم انجام می دهد باشد: بسیار شبیه به آنچه برای دوستتان تعریف می کنید.
✔️ به نمونه کد های زیر دقت کنید و هر دو یک کار را انجام می دهند اما...
(A-2)
(ادامه دارد)
🔵تجاربی از کار با MATLAB که سال ها طول می کشد یاد بگیرید(ادامه)🔵
(پیش نیاز: بدون پیش نیاز)
@MatlabTips
5⃣ متغیر هایتان را هارد کد(Hardcode) نکنید:
اگر اندازه متغیری که استفاده می کنید در حدود یک ماتریس 3 در 3 باشد مشکلی برای نوشتن آن در فایل کد( با پسوند .m) نیست. اما اگر متغیری که دارید بزرگتر از اندازه معمول( بالاتر از چند مگابایت) بود بهتر است آن را در یک فایل جداگانه بگذارید و آن را بخوانید تا هم قابلیت استفاده دوباره کد خود را بالا ببرید و هم بهتر قابل خواندن باشد.(بعدا در این مورد مطالبی قرار خواهیم داد.)
6⃣ فایل هایِ کد بزرگ نسازید:
یکی از مواردی که بسیاری از برنامه نویسان مبتدی را زود از کار خسته می کند نوشتن برنامه های بزرگ در یک فایل است. این البته ربطی به ذهن آن ها ندارد حتی یک برنامه نویس حرفه ای هم با دیدن یک فایل بسیار بزرگ شامل چند صد خط کد، گیج و سردر گم می شود. برای شکستن برنامه تان می توانید از برنامه نویسی شی گرا استفاده کنید یا اگر با مفاهیم شی گرایی آشنا نیستید حداقل از توابع استفاده کنید. یک راه خوب این است که با خودتان قرار بگذارید که هر تابعی که می نویسید حداکثر در یک صفحه (بدون اسکرول کردن) قابل دیدن باشد. این کار شاید همیشه ممکن نباشد. اما حداقل با استفاده از کامنت قسمت های کد را به صورت منطقی از هم جدا کنید. با %% می توان برنامه را بخش بندی کرد. در شکل زیر یک نمونه از بخش بندی برنامه با استفاده از همین روش میبینید. در هر قسمت که کلیک میکنید آن قسمت به صورت زرد رنگ(در ادیتور MATLAB) نمایش داده می شود.
7⃣ از متغیر های Global دوری کنید:
نمی توان کدی که شامل متغیر های Global هست را یک کد خوب دانست. دلیل ساده آن این است که وقتی از متغیر Global استفاده می کنید خودتان هم نمی دانید که بازه(scope) متغیرتان کجاست.(تنها یک استثنا برای آن وجود دارد و آن هم توابع tic و toc است)
@MatlabTips
(A-2)
(پیش نیاز: بدون پیش نیاز)
@MatlabTips
5⃣ متغیر هایتان را هارد کد(Hardcode) نکنید:
اگر اندازه متغیری که استفاده می کنید در حدود یک ماتریس 3 در 3 باشد مشکلی برای نوشتن آن در فایل کد( با پسوند .m) نیست. اما اگر متغیری که دارید بزرگتر از اندازه معمول( بالاتر از چند مگابایت) بود بهتر است آن را در یک فایل جداگانه بگذارید و آن را بخوانید تا هم قابلیت استفاده دوباره کد خود را بالا ببرید و هم بهتر قابل خواندن باشد.(بعدا در این مورد مطالبی قرار خواهیم داد.)
6⃣ فایل هایِ کد بزرگ نسازید:
یکی از مواردی که بسیاری از برنامه نویسان مبتدی را زود از کار خسته می کند نوشتن برنامه های بزرگ در یک فایل است. این البته ربطی به ذهن آن ها ندارد حتی یک برنامه نویس حرفه ای هم با دیدن یک فایل بسیار بزرگ شامل چند صد خط کد، گیج و سردر گم می شود. برای شکستن برنامه تان می توانید از برنامه نویسی شی گرا استفاده کنید یا اگر با مفاهیم شی گرایی آشنا نیستید حداقل از توابع استفاده کنید. یک راه خوب این است که با خودتان قرار بگذارید که هر تابعی که می نویسید حداکثر در یک صفحه (بدون اسکرول کردن) قابل دیدن باشد. این کار شاید همیشه ممکن نباشد. اما حداقل با استفاده از کامنت قسمت های کد را به صورت منطقی از هم جدا کنید. با %% می توان برنامه را بخش بندی کرد. در شکل زیر یک نمونه از بخش بندی برنامه با استفاده از همین روش میبینید. در هر قسمت که کلیک میکنید آن قسمت به صورت زرد رنگ(در ادیتور MATLAB) نمایش داده می شود.
7⃣ از متغیر های Global دوری کنید:
نمی توان کدی که شامل متغیر های Global هست را یک کد خوب دانست. دلیل ساده آن این است که وقتی از متغیر Global استفاده می کنید خودتان هم نمی دانید که بازه(scope) متغیرتان کجاست.(تنها یک استثنا برای آن وجود دارد و آن هم توابع tic و toc است)
@MatlabTips
(A-2)
🔵دسترسی بهینه به عناصر ماتریسها در MATLAB🔵
پیشنیاز: آشنایی مقدماتی با کد نویسی در MATLAB
یک راه ساده برای بهبود عملکرد کد MATLAB دسترسی به عناصر ماتریسهای چندبعدی به شیوهای است که خود MATLAB آنها را درون حافظه ذخیرهسازی میکند.
ماتریس A را در نظر بگیرید:
| a11 a12 a13 |
A =| a21 a22 a23 |
| a31 a32 a33 |
اگرچه این یک ماتریس دو بعدی است، دادههای آن بصورت ترتیبی در حافظه کامپیوتر ذخیره میشود. برای تبدیل ماتریسهای چندبعدی به نمایش آرایههای ترتیبی، MATLAB از فرمت بر اساس ستون (column-major) استفاده میکند. در این فرمت عناصر یک ستون ابتدا ذخیره شده و سپس عناصر ستون کناری به دنبال آن ذخیره میشود. در حالت ستون بیس، ماتریس A بصورت زیر ذخیره می شود.
[a11 a21 a31 a12 a22 a32 a13 a23 a33]
مثال:
این کد بر اساس ردیف (row-major) عناصر ماتریس را میخواند.
این کد بر اساس ستون به عناصر ماتریس دسترسی دارد و 1.7 برابر (در ماشین من) سریعتر است.
@MatlabTips
پیشنیاز: آشنایی مقدماتی با کد نویسی در MATLAB
یک راه ساده برای بهبود عملکرد کد MATLAB دسترسی به عناصر ماتریسهای چندبعدی به شیوهای است که خود MATLAB آنها را درون حافظه ذخیرهسازی میکند.
ماتریس A را در نظر بگیرید:
| a11 a12 a13 |
A =| a21 a22 a23 |
| a31 a32 a33 |
اگرچه این یک ماتریس دو بعدی است، دادههای آن بصورت ترتیبی در حافظه کامپیوتر ذخیره میشود. برای تبدیل ماتریسهای چندبعدی به نمایش آرایههای ترتیبی، MATLAB از فرمت بر اساس ستون (column-major) استفاده میکند. در این فرمت عناصر یک ستون ابتدا ذخیره شده و سپس عناصر ستون کناری به دنبال آن ذخیره میشود. در حالت ستون بیس، ماتریس A بصورت زیر ذخیره می شود.
[a11 a21 a31 a12 a22 a32 a13 a23 a33]
مثال:
این کد بر اساس ردیف (row-major) عناصر ماتریس را میخواند.
X = randn(N);
Y = zeros(N);
for row = 1:N % Row
for col = 1:N % Column
if X(row,col) >= 0
Y(row,col) = X(row,col);
end
end
end
این کد بر اساس ستون به عناصر ماتریس دسترسی دارد و 1.7 برابر (در ماشین من) سریعتر است.
N = 5e3;
X = randn(N);
Y = zeros(N);
for col = 1:N % Column
for row = 1:N % Row
if X(row,col) >= 0
Y(row,col) = X(row,col);
end
end
end
@MatlabTips
🔵آزمون محک در Matlab🔵
پیشنیاز : (پیشنیاز ندارد)
فرمان bench شش کار متفاوت در Matlab اعم از (LU, FFT,ODE, …) را برای آزمون محک (test bench) در نظر میگیرد. سرعت اجرای این کارها بر روی سیستم شما با سرعت اجرای آنها بر روی چندین کامپیوتر دیگر مقایسه میشود.
نمودرا میلهای که در پایان ظاهر میشود، سرعت را نمایش میدهد. میلههای بزرگتر بیانگر ماشینهای سریعتر هستند و میلههای کوچکتر بیانگر ماشینهای کندتر.
✔️مثال:
دستور زیر را در پنجره فرمان (command window) وارد کرده تا قدرت سیستم خود را با سیستم های موجود مقایسه کنید.
@MatlabTips
(A-1)
پیشنیاز : (پیشنیاز ندارد)
فرمان bench شش کار متفاوت در Matlab اعم از (LU, FFT,ODE, …) را برای آزمون محک (test bench) در نظر میگیرد. سرعت اجرای این کارها بر روی سیستم شما با سرعت اجرای آنها بر روی چندین کامپیوتر دیگر مقایسه میشود.
نمودرا میلهای که در پایان ظاهر میشود، سرعت را نمایش میدهد. میلههای بزرگتر بیانگر ماشینهای سریعتر هستند و میلههای کوچکتر بیانگر ماشینهای کندتر.
✔️مثال:
دستور زیر را در پنجره فرمان (command window) وارد کرده تا قدرت سیستم خود را با سیستم های موجود مقایسه کنید.
>> bench
@MatlabTips
(A-1)
🔵کاهش پیچیدگی محاسباتی🔵
#SpeedUp
پیش نیاز: (آشنایی مقدماتی با کدنویسی)
سطح پیچیدگی:🌕🌓🌑🌑🌑
در هنگام اجرای هر نوع پردازش روابط ریاضی بهتر است معادلهای سادهتر آن را یافته و در کد استفاده کنیم. در این موارد حتی اگر کد کاملا برداریشده باشد استفاده از این روش میتواند کد را سریعتر کند. دو عملگر + و – از عملگرهای * و / سریعتر هستند و این دو عملگر از توان سریعتر عمل میکنند.
✔️به مثال زیر توجه کنید که چگونه عملگرها را به لحاظ عملکرد با یکدیگر مقایسه میکند. دقت کنید که کد اول که از عملگر توان استفاده می کند چندین برابر کندتر از معادل های دیگر خود می باشد.
@MatlabTips
(A-1)
#SpeedUp
پیش نیاز: (آشنایی مقدماتی با کدنویسی)
سطح پیچیدگی:🌕🌓🌑🌑🌑
در هنگام اجرای هر نوع پردازش روابط ریاضی بهتر است معادلهای سادهتر آن را یافته و در کد استفاده کنیم. در این موارد حتی اگر کد کاملا برداریشده باشد استفاده از این روش میتواند کد را سریعتر کند. دو عملگر + و – از عملگرهای * و / سریعتر هستند و این دو عملگر از توان سریعتر عمل میکنند.
✔️به مثال زیر توجه کنید که چگونه عملگرها را به لحاظ عملکرد با یکدیگر مقایسه میکند. دقت کنید که کد اول که از عملگر توان استفاده می کند چندین برابر کندتر از معادل های دیگر خود می باشد.
%% slow approach using a.^n
a = 0.9999; n = 10000;
for idx=1:1000
y=a.^(1:n);
end
%% Using exp(log(a)*n) - 8x faster
for idx=1:1000
y=exp(log(a)*(1:n));
end
%% Using cumprod(a) - 40x faster
for idx=1:1000
y=cumprod(zeros(1,n)+a);
end
@MatlabTips
(A-1)
🔵روش برداری یا حلقه؟🔵
(پیش نیاز: آشنایی مقدماتی با کدنویسی)
سطح پیچیدگی:🌕🌓🌑🌑🌑
چند سال پیش وقتی کمک درس MATLAB بودم در کلاس در مورد مزایای برداری سازی و دوری کردن از حلقه های for به شدت گرم صحبت بودم. سپس تصمیم گرفتم که به صورت زنده به دانشجویان نشان دهم که حرف هایم درست است، بنابراین تصمیم گرفتم برنامه ای مشابه برنامه زیر بنویسم:
این برنامه یک بردار از اعداد یک تا 10 میلیون را یک بار در حلقه for و دفعه بعدی به صورت برداری تک تک در 5 ضرب می کند. اما وقتی برنامه اجرا شد کاملا شوکه شدم چون حلقه سریع تر بود.(روی سیستم من الان)
For loop: 0.0923s
Vectorized: 0.1235s
بنابراین تصمیم گرفتم تغییرات دیگری در برنامه بدهم: مثلا تعداد را بیشتر کنم اما فایده ای نداشت. آنچه خوانده بودم انگار اشتباه بود. کم کم صدای خنده بچه ها بلند شده بود و من کاملا شرمنده شدم.
اما دلیل این اتفاق چه بود؟ چند سال پیش MATLAB یک قسمت به نام شتاب دهنده درجا (Just-In-Time(JIT) Accelerator) معرفی کرد. JIT در پشت صحنه اجرا می شود و بنابراین خیلی ها از آن خبر ندارند. وظیفه JIT آن است که کد های MATLAB را کامپایل می کند و دیگر به جای آن که خط به خط اجرا شود (چون MATLAB یک زبان مفسری است و به صورت پیش فرض باید خط به خط اجرا شود) قسمت هایی از کد را کامپایل کرده و در نهایت قسمت های کامپایل شده را اجرا می کند. حالا اگر به صورت دستی JIT را با دستور زیر خاموش کنیم:
نتایج به صورت زیر هستند:
For loop: 18.0181s
Vectorized: 0.1035s
همانطور که می بینید سرعت محاسبه برداری 174 برابر است.
تمام این ها را گفتم تا به این نقطه برسم که به شما توصیه کنم همچنان از بردار ها استفاده کنید! JIT دارای مشکلات زیادی است چرا که برنامه شما را در بسیاری از مواقع به صورت نادرستی بهینه می کند همچنین ناپایدار است و در نسخه های مختلف متلب نتایج متفاوتی به شما می دهد. از طرفی نوشتن برنامه با استفاده از بردار آن ها را ساده تر و نگهداری و بازنویسی کد ها را راحت تر می کند.
مایکل گلبارت مدرس دانشگاه بریتیش کلمبیا
@MatlabTips
#SpeedUp, #JIT
مترجم: (A-2)
(پیش نیاز: آشنایی مقدماتی با کدنویسی)
سطح پیچیدگی:🌕🌓🌑🌑🌑
چند سال پیش وقتی کمک درس MATLAB بودم در کلاس در مورد مزایای برداری سازی و دوری کردن از حلقه های for به شدت گرم صحبت بودم. سپس تصمیم گرفتم که به صورت زنده به دانشجویان نشان دهم که حرف هایم درست است، بنابراین تصمیم گرفتم برنامه ای مشابه برنامه زیر بنویسم:
N = 1e7;
tic
w = zeros(1, N);
for i = 1:N
w(i) = i*5;
end
fprintf('For loop: %.4fs\n', toc);
tic
y = (1:N)*5;
fprintf('Vectorized: %.4fs\n', toc);
این برنامه یک بردار از اعداد یک تا 10 میلیون را یک بار در حلقه for و دفعه بعدی به صورت برداری تک تک در 5 ضرب می کند. اما وقتی برنامه اجرا شد کاملا شوکه شدم چون حلقه سریع تر بود.(روی سیستم من الان)
For loop: 0.0923s
Vectorized: 0.1235s
بنابراین تصمیم گرفتم تغییرات دیگری در برنامه بدهم: مثلا تعداد را بیشتر کنم اما فایده ای نداشت. آنچه خوانده بودم انگار اشتباه بود. کم کم صدای خنده بچه ها بلند شده بود و من کاملا شرمنده شدم.
اما دلیل این اتفاق چه بود؟ چند سال پیش MATLAB یک قسمت به نام شتاب دهنده درجا (Just-In-Time(JIT) Accelerator) معرفی کرد. JIT در پشت صحنه اجرا می شود و بنابراین خیلی ها از آن خبر ندارند. وظیفه JIT آن است که کد های MATLAB را کامپایل می کند و دیگر به جای آن که خط به خط اجرا شود (چون MATLAB یک زبان مفسری است و به صورت پیش فرض باید خط به خط اجرا شود) قسمت هایی از کد را کامپایل کرده و در نهایت قسمت های کامپایل شده را اجرا می کند. حالا اگر به صورت دستی JIT را با دستور زیر خاموش کنیم:
feature('accel','off') %this line shuts down the JIT
N = 1e7;
tic
w = zeros(1, N);
for i = 1:N
w(i) = i*5;
end
fprintf('For loop: %.4fs\n', toc);
tic
y = (1:N)*5;
fprintf('Vectorized: %.4fs\n', toc);
نتایج به صورت زیر هستند:
For loop: 18.0181s
Vectorized: 0.1035s
همانطور که می بینید سرعت محاسبه برداری 174 برابر است.
تمام این ها را گفتم تا به این نقطه برسم که به شما توصیه کنم همچنان از بردار ها استفاده کنید! JIT دارای مشکلات زیادی است چرا که برنامه شما را در بسیاری از مواقع به صورت نادرستی بهینه می کند همچنین ناپایدار است و در نسخه های مختلف متلب نتایج متفاوتی به شما می دهد. از طرفی نوشتن برنامه با استفاده از بردار آن ها را ساده تر و نگهداری و بازنویسی کد ها را راحت تر می کند.
مایکل گلبارت مدرس دانشگاه بریتیش کلمبیا
@MatlabTips
#SpeedUp, #JIT
مترجم: (A-2)
🔵نگهداری در برابر عملکرد🔵
پیشنیاز: (پیشنیاز ندارد)
سطح پیچیدگی:🌒🌑🌑🌑🌑
گاهی اوقات فهم کدی که بهینهشده است (به لحاظ سرعت اجرا) دشوارتر است. برای مثال، کد mex (در پستهای بعدی توضیح داده خواهد شد) نسبت به معادل m-file خود پیچیدهتر است؛ گاهی اوقات برداریسازیهای پیچیده نسبت به حلقههای ساده فهم کد را دشوارتر کرده و برای اصلاح و نگهداری آن در آینده ممکن است دچار مشکل شوید.
شاید دوست داشته باشید که یک کد سریع بنویسید صرف نظر از اینکه چقدر آن کد نامرتب و پیچیده باشد. اما دقت کنید هزینهای که در آینده برای تصحیح احتمالی یک کد نامرتب میپردازم ممکن است نسبت به زمانی که در افزایش سرعت کد ذخیره کرده ایم بسیار سنگین باشد.
اثر کامنتها بر روی عملکرد کد "صفر" است و با این وجود بسیار ارزشمند هستند. موقع نوشتن کد براحتی میتوانید آنچه در ذهنتان میگذرد بصورت کامنت در کد خود وارد کنید. شاید سال بعد فراموش کنید که کدتان چگونه کار میکرده است ولی همچنان نیاز دارید که آن را اصلاح و خطایابی (debug) کنید. بنابراین لختی زمان بگذارید و کامنتهایی برای توصیف کد خود قرار دهید و حتی توضیح دهید که چرا از فلان الگوریتم استفاده شده است و ... .
سعی کنید به تمیزی و طراحی مناسب کد عادت کنید. 10 تا 20 برابر زمانی که صرف نوشتن و تایپ کردن کد میکنیم، صرف خواندن آن میکنیم. سعی کنید به جای آنکه کد سریعی داشته باشید، در وهله اول کد تمیزی داشته باشید. زمان یک برنامهنویس تقریبا در تمام موارد از زمان ماشین با ارزشتر است.
@MatlabTips
#SpeedUp, #performance
نویسنده:(A-1)
پیشنیاز: (پیشنیاز ندارد)
سطح پیچیدگی:🌒🌑🌑🌑🌑
گاهی اوقات فهم کدی که بهینهشده است (به لحاظ سرعت اجرا) دشوارتر است. برای مثال، کد mex (در پستهای بعدی توضیح داده خواهد شد) نسبت به معادل m-file خود پیچیدهتر است؛ گاهی اوقات برداریسازیهای پیچیده نسبت به حلقههای ساده فهم کد را دشوارتر کرده و برای اصلاح و نگهداری آن در آینده ممکن است دچار مشکل شوید.
شاید دوست داشته باشید که یک کد سریع بنویسید صرف نظر از اینکه چقدر آن کد نامرتب و پیچیده باشد. اما دقت کنید هزینهای که در آینده برای تصحیح احتمالی یک کد نامرتب میپردازم ممکن است نسبت به زمانی که در افزایش سرعت کد ذخیره کرده ایم بسیار سنگین باشد.
اثر کامنتها بر روی عملکرد کد "صفر" است و با این وجود بسیار ارزشمند هستند. موقع نوشتن کد براحتی میتوانید آنچه در ذهنتان میگذرد بصورت کامنت در کد خود وارد کنید. شاید سال بعد فراموش کنید که کدتان چگونه کار میکرده است ولی همچنان نیاز دارید که آن را اصلاح و خطایابی (debug) کنید. بنابراین لختی زمان بگذارید و کامنتهایی برای توصیف کد خود قرار دهید و حتی توضیح دهید که چرا از فلان الگوریتم استفاده شده است و ... .
سعی کنید به تمیزی و طراحی مناسب کد عادت کنید. 10 تا 20 برابر زمانی که صرف نوشتن و تایپ کردن کد میکنیم، صرف خواندن آن میکنیم. سعی کنید به جای آنکه کد سریعی داشته باشید، در وهله اول کد تمیزی داشته باشید. زمان یک برنامهنویس تقریبا در تمام موارد از زمان ماشین با ارزشتر است.
@MatlabTips
#SpeedUp, #performance
نویسنده:(A-1)
🔵توجه🔵
دوستان میخواستم یه نکته ای درباره ویدئوهای ارسالی خدمتتون عرض کنم. تا اطلاع ثانوی ویدئوهایی که ارسال خواهد شد به چهار بخش تقسیم میشن
1⃣متلب پیش مقدماتی (Pre Elementary)
2⃣متلب مقدماتی(Elementary)
3⃣متلب پیشرفته(Advanced)
4⃣پردازش تصویر(Image_processing)
دوستانی که دنبال متلب پیشرفته هستن نیازی نیست حجمشون رو صرف دانلود متلب پیش مقدماتی یا مقدماتی کنن. ولی دوستانی که تازه میخوان متلب یاد بگیرن، میتونن ویدئوهای پیشرفته هم دانلود کنند و یه گوشه آرشیو کنند تا بعدا بتونن از اونا استفاده کنن. درآینده ویدوئوهای بسیار جذاب و عملی در زمینه های مختلف برای تمام سطوح در کانال قرار میدیم.
ممنون که ما را دنبال میکنید.
@MatlabTips
#Caution
نویسنده: (A-1)
دوستان میخواستم یه نکته ای درباره ویدئوهای ارسالی خدمتتون عرض کنم. تا اطلاع ثانوی ویدئوهایی که ارسال خواهد شد به چهار بخش تقسیم میشن
1⃣متلب پیش مقدماتی (Pre Elementary)
2⃣متلب مقدماتی(Elementary)
3⃣متلب پیشرفته(Advanced)
4⃣پردازش تصویر(Image_processing)
دوستانی که دنبال متلب پیشرفته هستن نیازی نیست حجمشون رو صرف دانلود متلب پیش مقدماتی یا مقدماتی کنن. ولی دوستانی که تازه میخوان متلب یاد بگیرن، میتونن ویدئوهای پیشرفته هم دانلود کنند و یه گوشه آرشیو کنند تا بعدا بتونن از اونا استفاده کنن. درآینده ویدوئوهای بسیار جذاب و عملی در زمینه های مختلف برای تمام سطوح در کانال قرار میدیم.
ممنون که ما را دنبال میکنید.
@MatlabTips
#Caution
نویسنده: (A-1)
🔵جبر خطی را به MATLAB بیاورید🔵
پیشنیاز: مقدمات جبر خطی، مقدمات برنامه نویسی
سطح پیچیدگی:🌕🌑🌑🌑🌑
برای بسیاری از شما پیش آمده است که فرمولی در یک مقاله دیده اید و فهمیده اید(یا حتی نفهمیده اید) اما وقتی می خواهید آن را پیاده سازی کنید ایده ای ندارید. در نهایت با 5 یا 6 حلقه تو در تو برنامه را می نویسید که نه تنها فهم آن سخت است بلکه عیب یابی آن شما را به حد عصبانیت می رساند. مهم ترین دلیل این اتفاق این است که شما فرمول را به درستی به متلب وارد نکرده اید. متلب یک زبان برنامه نویسی مبتنی بر ماتریس هاست بنابراین شما هم باید از امکانات آن استفاده کنید. در غیر این صورت برنامه را با زبان های دیگر می نوشتید. در این سری قصد داریم کمی دقیق تر به متغیر های متلب نگاه کنیم و با مثال همه ی زوایای پنهان متغیرها که بسیار کاربردی هستند را روشن کنیم.
در ریاضی خوانده ایم که حداقل سه نوع متغیر داریم: اسکالر(یک متغیر تک)، بردار(سطری و ستونی) و ماتریس. در MATLAB هم دقیقا همین ها را داریم:
به طور کلی وقتی MATLAB بر روی موجودیت دوست داشتنی اش یعنی ماتریس عمل می کند بر روی همه ی اعضای آن عمل می کند و دقیقا همین باعث قدرتمند بودن آن می شود.
حالا حالت های مختلف ضرب را بررسی می کنیم: (در نماد گذاری زیر حروف a,b,c نشان دهنده اسکالر، x نشان دهنده بردار و X نشان دهنده ماتریس است. همچنین سمت چپ فلش نماد ریاضی و سمت راست سینتکس معادل در MATLAB را نشان می دهد)
1- ضرب یک اسکالر(یک متغیر عددی) در اسکالر، بردار و ماتریس:
پیشنیاز: مقدمات جبر خطی، مقدمات برنامه نویسی
سطح پیچیدگی:🌕🌑🌑🌑🌑
برای بسیاری از شما پیش آمده است که فرمولی در یک مقاله دیده اید و فهمیده اید(یا حتی نفهمیده اید) اما وقتی می خواهید آن را پیاده سازی کنید ایده ای ندارید. در نهایت با 5 یا 6 حلقه تو در تو برنامه را می نویسید که نه تنها فهم آن سخت است بلکه عیب یابی آن شما را به حد عصبانیت می رساند. مهم ترین دلیل این اتفاق این است که شما فرمول را به درستی به متلب وارد نکرده اید. متلب یک زبان برنامه نویسی مبتنی بر ماتریس هاست بنابراین شما هم باید از امکانات آن استفاده کنید. در غیر این صورت برنامه را با زبان های دیگر می نوشتید. در این سری قصد داریم کمی دقیق تر به متغیر های متلب نگاه کنیم و با مثال همه ی زوایای پنهان متغیرها که بسیار کاربردی هستند را روشن کنیم.
در ریاضی خوانده ایم که حداقل سه نوع متغیر داریم: اسکالر(یک متغیر تک)، بردار(سطری و ستونی) و ماتریس. در MATLAB هم دقیقا همین ها را داریم:
a=3%scalar
x=[1,2,3]% row vector
y=[1;2;3]% column vector
A=[1,2,3;4,5,6]% matrix
به طور کلی وقتی MATLAB بر روی موجودیت دوست داشتنی اش یعنی ماتریس عمل می کند بر روی همه ی اعضای آن عمل می کند و دقیقا همین باعث قدرتمند بودن آن می شود.
حالا حالت های مختلف ضرب را بررسی می کنیم: (در نماد گذاری زیر حروف a,b,c نشان دهنده اسکالر، x نشان دهنده بردار و X نشان دهنده ماتریس است. همچنین سمت چپ فلش نماد ریاضی و سمت راست سینتکس معادل در MATLAB را نشان می دهد)
1- ضرب یک اسکالر(یک متغیر عددی) در اسکالر، بردار و ماتریس:
برنامهMATLAB زیر یک نمونه از این حالات را به ترتیب نشان می دهد:
1- ضرب بردار در بردار: دو حالت ممکن برای ضرب دو بردار در هم وجود دارد. در حالت اول یک بردار ستونی(N*1) یعنی x در یک بردار سطری ( 1*M) یعنی y ضرب شده و نتیجه یک ماتریس است:
a = 3;
b = 4;
a * b %scalar by scalar
a = 3;
x = [1, 3, 7];
a * x %scalar by vector
a = 3;
X = [1, 2 ,4 ;5, 2, 3];
a * X %scalar by matrix
1- ضرب بردار در بردار: دو حالت ممکن برای ضرب دو بردار در هم وجود دارد. در حالت اول یک بردار ستونی(N*1) یعنی x در یک بردار سطری ( 1*M) یعنی y ضرب شده و نتیجه یک ماتریس است:
کد MATLAB زیر یک نمونه از این حالت را نشان می دهد:
3- ضرب ماتریس در بردار: اگر اندازه های ماتریس و بردار با هم سازگار باشد قابل ضرب کردن هستند. به طور مثال ماتریس N*M یعنی A در یک بردار ستونی M*1 یعنی x ضرب شده است و نتیجه یک بردار ستونی N*1 است:
x = [5, 2, 4];%row vector
y = [3; 1; 2];%column vector
x * y %dot product
y * x %produce a 3*3 matrix
3- ضرب ماتریس در بردار: اگر اندازه های ماتریس و بردار با هم سازگار باشد قابل ضرب کردن هستند. به طور مثال ماتریس N*M یعنی A در یک بردار ستونی M*1 یعنی x ضرب شده است و نتیجه یک بردار ستونی N*1 است: