Struggling a bit with writing a function and passing it to the GPU with via arrayfun
조회 수: 3 (최근 30일)
이전 댓글 표시
I have a long equation that I am currently looping though element by element and its taking forever so I want to make it faster. I’ve read that you can use arrayfun to apply a function to each element using the GPU which could sometimes decrease the computational time a lot. Not sure that method is applicable in all situations (like this one for example), but since I have the parallel computing toolbox I thought I would try it, but I’m not getting it to work, maybe I’m writing the function In the wrong way, I’m trying to understand this but I’m still stuck a bit in my old mindset of working with nested loops which Im trying to get away from.
This is the function file I have created:
function [o1] = IncAngle(DailyDeclination,DailyHourAngle,Azimuth,Tilt)
o1=acosd(cosd(DailyDeclination)*sind(DailyHourAngle)*sind(Tilt)*sind(Azimuth)+cosd(DailyDeclination)*cosd(DailyHourAngle)*sind(57.6)*sind(Tilt)*cosd(Azimuth)-sind(DailyDeclination)*cosd(57.6)*sind(Tilt)*cosd(Azimuth)+cosd(DailyDeclination)*cosd(DailyHourAngle)*cosd(57.6)*cosd(Tilt)+sind(DailyDeclination)*sind(57.6)*cosd(Tilt));
As you can see it’s a bit long and complicated, but the outcome depends on four variables:
DailyDeclination % a 1x1440, each value representing one minute of a day
DailyHourAngle % a 1x1440, each value representing one minute of a day
Azimuth=(-179:2:180)'; % a 180x1, each value representing one orientation on a compass
Tilt=(0:1:180)'; % a 181x1 , each value representing one degree tilt of a surface
And I want the output to be stored as 1440x181x180 representing all minutes during the day for all combinations of tilts and orientations. This is how I try to pass the function to the GPU which I am basing on something similar I saw in an example:
DailyDeclination = gpuArray(DailyDeclination);
DailyHourAngle = gpuArray(DailyHourAngle);
Azimuth = gpuArray(Azimuth);
Tilt = gpuArray(Tilt);
[o1]=arrayfun(@IncAngle,DailyDeclination,DailyHourAngle,Azimuth,Tilt)
But it only gives me the error: Error using gpuArray/arrayfun Non-singleton dimensions of input arrays must match each other.
I suspect that the error here isn’t just because I’m sending it to the GPU, but that I’m not writing the function input/outputs correctly. How do I specify for the function in which order the elements should be combined and how I want my output to look without using for loops?
댓글 수: 0
채택된 답변
Edric Ellis
2015년 3월 19일
To use arrayfun in this way, you need each of your vectors to define a different dimension. Something like this simplified example:
% a column vector
v1 = reshape(gpuArray.colon(1, 3), [], 1);
% a row vector
v2 = gpuArray.colon(1, 4);
% 3rd-dimension vector
v3 = reshape(gpuArray.colon(1, 5), 1, 1, []);
% add together elements
arrayfun(@(x,y,z) x + y + z, v1, v2, v3)
In your case, you'll need transpose DailyDeclination and DailyHourAngle to be columns, Tilt needs to be a row (so don't transpose that), and you need to reshape Azimuth to be a 3rd-dimension vector.
댓글 수: 2
Edric Ellis
2015년 3월 20일
Yes, the precise double-precision arithmetic on the GPU doesn't always exactly match the CPU - especially when using trig functions etc. The results should be close to within a few eps though depending on how many operations are involved.
추가 답변 (0개)
참고 항목
카테고리
Help Center 및 File Exchange에서 GPU Computing in MATLAB에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!