问题
Please correct me if there are somethings unclear in this question. I have two matrices pop
, and ben
of 3 dimensions. Call these dimensions as c,t,w
. I want to repeat the exact same process I describe below for all of the c
dimensions, without using a for loop as that is slow. For the discussion below, fix a value of the dimension c
, to explain my thinking, later I will give a MWE. So when c is fixed I have a 2D matrix with dimension t,w
.
Now I repeat the entire process (coming below!) for all of the w dimension.
If the value of u is zero, then I find the next non zero entry in this same t dimension. I save both this entry as well as the corresponding t index. If the value of u is non zero, I simply store this value and the corresponding t index. Call the index as i - note i would be of dimension (c,t,w)
. The last entry of every u(c,:,w)
is guaranteed to be non zero.
Example if the u(c,:,w)
vector is [ 3 0 4 2 0 1], then the corresponding i values are [1,3,3,4,6,6]
.
Now I take these entries and define a new 3d array of dimension (c,t,w)
as follows. I take my B array and do the following what is not a correct syntax but to explain you: B(c,t,w)/u(c,i(c,t,w),w)
. Meaning I take the B
values and divide it by the u
values corresponding to the non zero indices of u from i that I computed.
For the above example, the denominator would be [3,4,4,2,1,1]
. I hope that makes sense!!
QUESTION:
To do this, as this process simply repeats for all c
, I can do a very fast vectorizable calculation for a single c. But for multiple c I do not know how to avoid the for loop. I don't knw how to do vectorizable calculations across dimensions.
Here is what I did, where c_size is the dimension of c.
for c=c_size:-1:1
uu=squeeze(pop(c,:,:)) ; % EXTRACT A 2D MATRIX FROM pop.
BB=squeeze(B(c,:,:)) ; % EXTRACT A 2D MATRIX FROM B
ii = nan(size(uu)); % Start with all nan values
[dum_row, ~] = find(uu); % Get row indices of non-zero values
ii(uu ~= 0) = dum_row; % Place row indices in locations of non-zero values
ii = cummin(ii, 1, 'reverse'); % Column-wise cumulative minimum, starting from bottomi
dum_i = ii+(time_size+1).*repmat(0:(scenario_size-1), time_size+1, 1); % Create linear index
ben(c,:,:) = BB(dum_i)./uu(dum_i);
i(c,:,:) = ii ;
clear dum_i dum_row uu BB ii
end
The central question is to avoid this for loop.
Related questions:
- Vectorizable FIND function with if statement MATLAB
- Efficiently finding non zero numbers from a large matrix
- Vectorizable FIND function with if statement MATLAB
来源:https://stackoverflow.com/questions/60799304/vectorizing-a-parallel-for-loop-across-multiple-dimensions-matlab