Hi all,
is there a way to vectorize the following loop?
for RIPETIZIONE = 1:10
%for k = 1:size(lambda_tol_vector.Value,1)
parfor (k = 1:size(lambda_tol_vector.Value,1))
%fprintf('Completion using nuclear norm regularization... \n');
[CompletedMat,flag] = matrix_completion_nuclear_GG_vec( ...
A.Value.*double(B), double(B), N, lambda_tol_vector.Value(k), tol);
if flag==1
CompletedMat_parvec{RIPETIZIONE,k}=zeros(size(A));
end
CompletedMat_parvec{RIPETIZIONE,k}=CompletedMat;
end
end

5 个评论

Move the PARFOR loops outside. Starting a parallel loop inside another loop is expensive.
The main part happens inside matrix_completion_nuclear_GG_vec(), so post this code instead of the outer loops.
What are the input values? If B is a large array, creating a copy in double format can be expensive already. Then doing this once only can increase the speed already. A.Value.*double(B) is a constand also. So do not claculate it repeatedly, but once before the loops.
What is the purpose of checking the values of flag?
if flag==1
CompletedMat_parvec{RIPETIZIONE,k}=zeros(size(A));
end
CompletedMat_parvec{RIPETIZIONE,k}=CompletedMat;
This wasted time only, because if flag equals 1, the output is filled by a zero array, but overwritten directly. Maybe you want:
if flag==1
CompletedMat_parvec{RIPETIZIONE,k}=zeros(size(A));
else
CompletedMat_parvec{RIPETIZIONE,k}=CompletedMat;
end
If CompletedMat_parvec pre-allocated?
Hi @Jan aand thnks for the reply.
Yes CompletedMat_parvec is pre-allocated as a cell array: CompletedMat_parvec={};
However there is a huge time expense when I use the outer for loop.
Please, refer to this thred to see the matrix_completion_nuclear_GG_vec function
As far as the input are concerned you can use these:
clear
%reduce the size of A if necessary.
A=rand(646,200);
B=int8(rand(size(A,1),size(A,2))>0.5);
lambda_tol=0.000000000000004;
N=10;
Jan
Jan 2022-11-28
编辑:Jan 2022-11-28
"Yes CompletedMat_parvec is pre-allocated as a cell array: CompletedMat_parvec={};" - This is not a pre-allocation. Pre-allocating means, to create the array with the final size instead of letting it grow iteratively.
I do not find the code of matrix_completion_nuclear_GG_vec in the other thread, but only matrix_completion_nuclear_GG_alt. Please do not let the readers guess, which code you are using.
By the way, avoid overdoing when naming functions. Too long functions names let you loose the overview.
Oh sorry @Jan.
I will attach the function here.
As for pre-allocation I will check the best way to pre-allocate vell arrays.
Oh @Jan another thing that I am nnoticing when putting the arfor loop on the outer one, is tht the final results in term of CompletedMat_parvec is different from the same result when I use only for loos (both outer and inner). Is there a way to make the two results equal?

请先登录,再进行评论。

 采纳的回答

Matt J
Matt J 2022-11-28
编辑:Matt J 2022-11-28
EDITED:
R=10;
K=size(lambda_tol_vector.Value,1);
CompletedMat_parvec=cell(R,K);
B=double(B);
parfor n=1:R*K
[RIPETIZIONE,k]=ind2sub([R,K],n);
%fprintf('Completion using nuclear norm regularization... \n');
[CompletedMat,flag] = matrix_completion_nuclear_GG_vec( ...
A.Value.*B,B, N, lambda_tol_vector.Value(k), tol);
if ~flag
CompletedMat_parvec{n}=CompletedMat;
end
end
idx=cellfun('isempty', CompletedMat_parvec);
CompletedMat_parvec(idx)={zeros(size(A))};

4 个评论

@Matt J thank you for the kind reply.
There is however a red flag in CompletedMat_parvec stating that valid indices for the latter are restricted in parfor loops:
Explanation
For MATLAB to execute parfor loops efficiently, the amount of data sent to the MATLAB workers must be minimal. One of the ways MATLAB achieves this is by restricting the way variables can be indexed in parfor iterations. The indicated variable is indexed in a way that is incompatible with parfor.
Suggested Action
Fix the indexing. For a description of the indexing restrictions, see Sliced Variables.
Maybe this line CompletedMat_parvec(1:R,1:K)={zeros(size(A))}; should be substituted by this one:
N_RIPETIZIONI=10;
L=size(lambda_tol_vector.Value,1);
CompletedMat_parvec= cell(N_RIPETIZIONI,L);
?
Try this replacement,
R=10; %
K=size(lambda_tol_vector.Value,1);
CompletedMat_parvec=cell(R,K);
B=double(B);
parfor n=1:R*K
[RIPETIZIONE,k]=ind2sub([R,K],n);
%fprintf('Completion using nuclear norm regularization... \n');
[CompletedMat,flag] = matrix_completion_nuclear_GG_vec( ...
A.Value.*B,B, N, lambda_tol_vector.Value(k), tol);
if ~flag
CompletedMat_parvec{n}=CompletedMat;
end
end
idx=cellfun('isempty', CompletedMat_parvec);
CompletedMat_parvec(idx)={zeros(size(A))};
@Matt J same problem unfortunately. Maaybe we should index it by n? Thhough I don't think so since ideally I need CompletedMat_parvec{RIPETIZIONE,k}=...;
Furthermore it looks like the variable n is not creted when evaluaating the parfor loop.
Yes! Sorry, you should be indexing by n,
if ~flag
CompletedMat_parvec{n}=CompletedMat;
end
It is equivalent to,
CompletedMat_parvec{RIPETIZIONE,k}=CompletedMat;

请先登录,再进行评论。

更多回答(0 个)

类别

帮助中心File Exchange 中查找有关 Loops and Conditional Statements 的更多信息

产品

版本

R2021b

Community Treasure Hunt

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

Start Hunting!

Translated by