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 Comments

Jan
Jan on 28 Nov 2022
Edited: Jan on 28 Nov 2022
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 on 28 Nov 2022
Edited: Jan on 28 Nov 2022
"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.
federico nutarelli
federico nutarelli on 28 Nov 2022
Edited: federico nutarelli on 28 Nov 2022
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?

Sign in to comment.

 Accepted Answer

Matt J
Matt J on 28 Nov 2022
Edited: Matt J on 28 Nov 2022
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 Comments

@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);
?
Matt J
Matt J on 28 Nov 2022
Edited: Matt J on 28 Nov 2022
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))};
federico nutarelli
federico nutarelli on 28 Nov 2022
Edited: federico nutarelli on 28 Nov 2022
@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.
Matt J
Matt J on 28 Nov 2022
Edited: Matt J on 28 Nov 2022
Yes! Sorry, you should be indexing by n,
if ~flag
CompletedMat_parvec{n}=CompletedMat;
end
It is equivalent to,
CompletedMat_parvec{RIPETIZIONE,k}=CompletedMat;

Sign in to comment.

More Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Products

Release

R2021b

Asked:

on 28 Nov 2022

Edited:

on 28 Nov 2022

Community Treasure Hunt

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

Start Hunting!