Asking for random numbers in a parallel loop always return the same pseudo random numbers. How can I avoid this?
% workers initialization:
if matlabpool('size') == 0
matlabpool('open',2);
else
matlabpool('close');
matlabpool('open',2);
end
% parallel loop always give the same random numbers...
parfor k = 1:10
fprintf([num2str(rand(1,1)), ' ']);
end
One ideal solution would be to initialize the pseudo random number generator in each thread by CPU time or similar. Things like rng('shuffle') don't seem to help here...
console output:
Sending a stop signal to all the workers ... stopped.
Starting matlabpool using the 'local' profile ... connected to 2 workers.
0.32457 0.66182 0.63488 0.64968
0.26459 0.096779 0.50518 0.48662 0.034895 0.85227
There is documentation here about various options here. Here's one way you might do something close.
numWorkers = matlabpool('size');
[streams{1:numWorkers}] = RandStream.create('mrg32k3a', ...
'Seed', 'shuffle', 'NumStreams', numWorkers);
spmd
RandStream.setGlobalStream(streams{labindex});
end
Or, to avoid creating all the streams at the client, you could do this instead:
rng('shuffle'); % shuffle the client
workerSeed = randi([0, 2^32-1]);
spmd
stream = RandStream.create('mrg32k3a', ...
'Seed', workerSeed, ...
'NumStreams', numlabs, ...
'StreamIndices', labindex);
RandStream.setGlobalStream(stream);
end
Related
I am trying to build a recursive tree structure in matlab. Since it is a pretty big tree I am trying to build, I want to speed up the calculation as much as possible, which is why I want to try making the calculation in parallel.
An example of what I am trying do may look like this:
function result = minimalExample(x)
n = numel(x);
if n == 0
result = 0;
return;
end
if n==1
result = x;
return
end
average = mean(x);
result = minimalExample(x(x<average))+minimalExample(x(x>average));
if any(x==average)
result = result*average;
end
end
I tried to use parfeval to do the calculation like this:
function result = minimalExampleParallel(x,pool)
n = numel(x);
if n == 0
result = 0;
return;
end
if n==1
result = x;
return
end
average = mean(x);
f(1) = parfeval(pool,#minimalExampleParallel,1,x(x<average),pool);
f(2) = parfeval(pool,#minimalExampleParallel,1,x(x>average),pool);
result = 0;
for i = 1:2
[~,value] = fetchNext(f);
result = result + value;
end
if any(x==average)
result = result*average;
end
end
But I get an Workers cannot execute parfeval or parfevalOnAll.-error.
I was hoping there would be a way of adding jobs to a global job queue that the workers may reach too, but I haven't been able to do so.
Is this in any way possible? And if so how? And if not so why?
I know you asked this quite some time ago, but I have an answer. I too was looking for such a solution, but could not find anything. There's nothing really posted online though so I want this to be here in case anyone else wants to know how.
You can do a sort of global job scheduler. Declare a parcluster then create separate jobs on said cluster using createCommunicatingJob. Then, and this is important, set the NumWorkersRange property of each job to something less than the total number of workers, preferably dividing them equally, though you can do it however you want. (Ex: If you have 12 workers and 4 jobs, set each worker range to [1 3]). If you do not do this, then it will queue the other tasks and only perform the first, as it will allocate all workers to the first task.
This works with functions that contain parfeval statements in them and the syntax is similar to parfeval. I verified using MATLAB's paralleldemo_blackjack_parfeval function. I hope this was what you were looking for. I know it's what I was looking for!
Link: http://www.mathworks.com/help/distcomp/createcommunicatingjob.html
Hi I want to run the code as below using PARFOR.
When I try it says that :
Valid indices for 'A_x' and 'A_y' 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” in the >Parallel Computing Toolbox documentation:
N=eveninteger;
H=zeros(N);
V=zeros(N);
A_x=zeros(N);
A_y=zeros(N);
parfor i=1:N;
for j=1:N;
if H(i,j)==-2;
t=0.3;
As_x=t*(j-i)/a;
As_y=t*(j-i)/a;
elseif H(i,j)==-3;
t=0.8;
As_x=t*(j-i)/(a*sqrt3);
As_y=t*(j-i)/(a*sqrt3);
elseif i==j
As_x=i;
As_y=i;
else
t=0;
As_x=0;
As_y=0;
end
for p=1:N/2
for q=N/2+1:N
A_x(p,q)=A_x(p,q)+As_x*(V(i,p)*V(j,q));
A_y(p,q)=A_y(p,q)+As_y*(V(i,p)*V(j,q));
end
end
end
end
I could not find solution. Could you offer me a solution.
Thanks in advance.
Erico
It looks like you're trying to perform a "reduction" on A_x and A_y using +. You might be able to work around this by doing something like the following:
parfor i = 1:N
A_x_tmp = zeros(N);
A_y_tmp = zeros(N);
for p=1:N/2
for q=N/2+1:N
A_x_tmp(p,q) = A_x_tmp(p,q) + ...
A_y_tmp(p,q) = A_y_tmp(p,q) + ...
end
end
A_x = A_x + A_x_tmp;
A_y = A_y + A_y_tmp;
end
In that way, PARFOR will understand the reduction operations on A_x and A_y.
I want to add an While-loop to my matlab-code so that it will stop when the iteration is good enough. With some kind of tolerance, eg. 1e-6.
This is my code now. So i need to add some kind of stopping criteria, i have tried several times now but it won't work... I appreciate all of ur help!
x(1)=1;
iterations = 0;
tolerance = 1e-6;
% Here should the while be....
for i=1:N
x(i+1)=x(i);
for j=1:N
x(i+1)=F(x(i),x(i+1));
end
end
iter= iter + 1;
Well, somehow you need to compute the 'error' you are doing in each iteration. In your case it would be something like this:
iter = 0;
tolerance = 1e-6;
error=1;
x=F(x);
while(error>tolerance)
x2=x;
x=F(x);
error = x-x2;
iter= iter + 1;
end
Note how at the beginning the error is set to 1 so we make sure it goes inside the loop. We also compute the first instance of x outside the loop. F(x) will be your function to evaluate, change it for whatever you need.
Inside the loop assign the old value of x to x2, then compute the new x and finally compute the error. Here I compute the error as x-x2 but you might need to compute this error in another way.
The loop will exit whenever the error is lower than the tolerance.
I am new to matlab and I do not know how to vectorize the following:
I have a large vector (think 30000) and I want to partition it into pieces of unequal length, specified by row indices into the vector. I have a function, which I want to apply to said peices parallelly(using parfor or otherwise), and stitch back the results.
Is there an efficient way to do this? any pointers will help.
First, run parpool to initialize a parallel pool in MATLAB (you need the parallel processing toolbox) to get some workers. Then use parfor to run a for loop in parallel by having each worker execute the loop at the same time. There are a few rules, such as each iteration in the loop cannot depend on or use results from the previous iteration.
Consider the following code:
% Run parpool first
n = 100000;
data = (1:n)';
myIndices = 1:5:n;
numSections = length(myIndices) -1;
f = #(x) mean(x);
outputMatrix = zeros(numSections,1);
% TRy changing this to parfor or just for and run a few times to see
% average time:
tic
parfor ind = 1:numSections
if ind == 1
myStart = 1;
else
myStart = myIndices(ind)+1;
end
myEnd = myIndices(ind+1);
outputCell{ind} = f(data(myStart:myEnd));
outputMatrix(ind) = f(data(myStart:myEnd));
end
toc
% convert cell array to matrix
output = cell2mat(outputCell);
Here I show how to collect in a cell or a vector/matrix. It depends on what kind of function you are running on your data. Try changing the parfor to for and running a few times to see the speed difference.
I chose to divide the data into even blocks of size 5 but you could change this to be whatever you want by making myIndices be arbitrary values.
Can anyone explain to me, why the following gives an error for u but nor for h
max_X = 100;
max_Y = 100;
h = ones(max_Y,max_X);
u = zeros(max_Y,max_X);
parfor l=1:max_X*max_Y
i = mod(l-1,max_X) + 1;
j = floor((l-1)/max_Y) + 1;
for k=1:9
m = i + floor((k-1)/3) - 1;
n = j + mod(k,-3) + 1;
h_average(k) = sqrt(h(i,j)*h(m,n));
u_average(k) = (u(i,j)*sqrt(h(i,j)) + u(m,n)*sqrt(h(m,n)))/(sqrt(h(i,j)) + sqrt(h(m,n)));
end
end
I can now substitute (i,j) with (l), but even if I try to calculate the related variable, let's call it p, according to (m,n), and write u(p) instead of u(m,n) it gives me an error message.
It only underlines the u(m,n), resp. u(p) but not the h(m,n).
MATLAB says:
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” in the Parallel Computing Toolbox documentation
Any idea, what's wrong here?
The problems with u and h are that they are both being sent as broadcast variables to the PARFOR loop. This is not an error - it's just a warning indicating that more data than might otherwise be necessary is being sent.
The PARFOR loop cannot run because you're indexing but not slicing u_average and h_average. It's not clear what outputs you want from this loop since you're overwriting u_average and h_average each time, therefore the PARFOR loop is pointless.