More efficient way than a loop for this particular example

I code but I am never trained for it, so every once in a while I get suspicious of the possibility to do something more efficiently. Bottleneck there is the ConvertColors in-house function I use, but I think there is a better way to do the j loop. Thanks in advance.
EDIT: for some reason the editor won't indent, so see screenshot for better readibility.
referenceAchromaticGrating=zeros(screenHeight_px,spatialFrequency_px,3);
for i=0:spatialFrequency_px-1
luminance = meanLuminance+4*sin(2*pi*(1/spatialFrequency_px)*i);
RGB_array = ConvertColors('MWLRGB',[0,0,luminance],colorInfo);
for j=1:3
referenceAchromaticGrating(:,i+1,j)=RGB_array(j);
end
end

 採用された回答

DGM
DGM 2022 年 2 月 15 日
編集済み: DGM 2022 年 2 月 15 日

1 投票

What size is RGB_array? I'm guessing it's a 1x3 tuple, and the LHS of the output assignment is a Mx1x3 region in the output array.
I doubt that trying to expand RGB_array to allow direct output assignment without the per-channel loop would really save more time.
However, it might be better to have the outer loop collect a Nx3 matrix of all values of RGB_array. At that point, once you're outside the loop, this array can be reshaped into the output.
RGB_array = zeros(spatialFrequency_px,3);
for i = 0:spatialFrequency_px-1
luminance = meanLuminance+4*sin(2*pi*(1/spatialFrequency_px)*i);
RGB_array(i+1,:) = ConvertColors('MWLRGB',[0,0,luminance],colorInfo);
end
referenceAchromaticGrating = repmat(permute(RGB_array,[3 1 2]),screenHeight_px,1);
This also avoids the need to preallocate the output array
I don't know if this is any faster than what you had. That's something you'll need to test.
EDIT:
I timed it (with ConvertColors() replaced with rand(1,3)). The above method is approximately twice as fast for a 1000x1000 output. It's slightly faster yet for smaller outputs. Including the functions that I omitted will only reduce the effective difference between the two.

4 件のコメント

Osman Kavcar
Osman Kavcar 2022 年 2 月 15 日
Both of your initial assumptions are correct. I ran the code, it works just as well, but to my surprise (as yours looks tidier and more proper to me) it ran slightly slower. However, I learned two functions that I have never used before (and certainly not in conjunction with each other).
Osman Kavcar
Osman Kavcar 2022 年 2 月 15 日
You were absolutely correct when rand is used (at least within my system).
Elapsed time is 0.010750 seconds. (yours)
Elapsed time is 0.012222 seconds. (mine)
So I tried with the ConvertColors function multiple times. My code fluctuated wildly (anywhere from 0.4 to 0.7 seconds) and yours remained consistent at around 0.5. This is so interesting.
DGM
DGM 2022 年 2 月 15 日
編集済み: DGM 2022 年 2 月 15 日
Take the results from tic/toc with a grain of salt -- the profiler even more.
This is what I used, though even version and environment differences can sway things.
spatialFrequency_px = 1000;
screenHeight_px = 1000;
% original method
a = timeit(@() testA(spatialFrequency_px,screenHeight_px))
a = 0.0050
% collect color table, permute, expand (faster)
b = timeit(@() testB(spatialFrequency_px,screenHeight_px))
b = 0.0022
% modified original with direct output assignment (slower)
c = timeit(@() testC(spatialFrequency_px,screenHeight_px))
c = 0.0150
% time ratios
[a/b a/c]
ans = 1×2
2.2055 0.3299
function testA(spatialFrequency_px,screenHeight_px)
referenceAchromaticGrating=zeros(screenHeight_px,spatialFrequency_px,3);
for i=0:spatialFrequency_px-1
RGB_array = rand(1,3);
for j=1:3
referenceAchromaticGrating(:,i+1,j)=RGB_array(j);
end
end
end
function testB(spatialFrequency_px,screenHeight_px)
RGB_array = zeros(spatialFrequency_px,3);
for i = 0:spatialFrequency_px-1
RGB_array(i+1,:) = rand(1,3);
end
referenceAchromaticGrating = repmat(permute(RGB_array,[3 1 2]),screenHeight_px,1);
end
function testC(spatialFrequency_px,screenHeight_px)
referenceAchromaticGrating=zeros(screenHeight_px,spatialFrequency_px,3);
for i=0:spatialFrequency_px-1
RGB_array = rand(1,3);
for j=1:3
referenceAchromaticGrating(:,i+1,:)= repmat(permute(RGB_array,[3 1 2]),[screenHeight_px 1]);
end
end
end
If ConvertColors() can be vectorized, there maybe more time to shave off.
Osman Kavcar
Osman Kavcar 2022 年 2 月 26 日
Thank you, this is marvelous!

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

ヘルプ センター および File ExchangeLoops and Conditional Statements についてさらに検索

製品

リリース

R2021a

質問済み:

2022 年 2 月 15 日

コメント済み:

2022 年 2 月 26 日

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by