I have figured out some awesome ways of speeding up my MATLAB code: vectorizing, arrayfun, and basically just getting rid of for loops (not using parfor). I want to take it to the next step.
Suppose I have 2 function calls that are computationally intensive.
x = fun(a);
y = fun(b);
They are completely independent, and I want to run them in parallel rather than serially. I dont have the parallel processing toolbox. Any help is appreciated.
thanks
If I am optimistic I think you ask "How Can I simply do parallel processing in Matlab". In that case the answer would be:
Parallel processing can most easily be done with the parallel computing toolbox. This gives you access to things like parfor.
I guess you can do:
parfor t = 1:2
if t == 1, x = fun(a); end
if t == 2, y = fun(b); end
end
Of course there are other ways, but that should be the simplest.
The MATLAB interpreter is single-threaded, so the only way to achieve parallelism across MATLAB functions is to run multiple instances of MATLAB. Parallel Computing Toolbox does this for you, and gives you a convenient interface in the form of PARFOR/SPMD/PARFEVAL etc. You can run multiple MATLAB instances manually, but you'll probably need to do a fair bit of work to organise the work that you want to be done.
The usual examples involve parfor, which is probably the easiest way to get parallelism out of MATLAB's Parallel Computing Toolbox (PCT). The parfeval function is quite easy, as demonstrated in this other post. A less frequently discussed functionality of the PCT is the system of jobs and tasks, which are probably the most appropriate solution for your simple case of two completely independent function calls. Spoiler: the batch command can help to simplify creation of simple jobs (see bottom of this post).
Unfortunately, it is not as straightforward to implement; for the sake of completeness, here's an example:
% Build a cluster from the default profile
c = parcluster();
% Create an independent job object
j = createJob(c);
% Use cells to pass inputs to the tasks
taskdataA = {field1varA,...};
taskdataB = {field1varB,...};
% Create the task with 2 outputs
nTaskOutputs = 2;
t = createTask(j, #myCoarseFunction, nTaskOutputs, {taskdataA, taskdataB});
% Start the job and wait for it to finish the tasks
submit(j); wait(j);
% Get the ouptuts from each task
taskoutput = get(t,'OutputArguments');
delete(j); % do not forget to remove the job or your APPDATA folder will fill up!
% Get the outputs
out1A = taskoutput{1}{1};
out1B = taskoutput{2}{1};
out2A = taskoutput{1}{2};
out2B = taskoutput{2}{2};
The key here is the function myCoarseFunction given to createTask as the function to evaluate in the task objects to creates. This can be your fun or a wrapper if you have complicated inputs/outputs that might require a struct container.
Note that for a single task, the entire workflow above of creating a job and task, then starting them with submit can be simplified with batch as follows:
c = parcluster();
jobA = batch(c, #myCoarseFunction, 1, taskdataA,...
'Pool', c.NumWorkers / 2 - 1, 'CaptureDiary', true);
Also, keep in mind that as with matlabpool(now called parpool), using parcluster requires time to startup the MATLAB.exe processes that will run your job.
Related
TL;DR: How should custom simulation runs be managed in Matlab? Detailed Questions at the end.
I am working with matlab where i created some code to check the influence of various parameters on a simulated system. It has a lot of inputs and outputs but a MWE would be:
function [number2x,next_letter] = test(number, letter)
number2x = number * 2;
next_letter = letter + 1;
disp(['next letter is ' next_letter])
disp(['number times 2 is ' num2str(number2x)])
end
This works if this is all there is to test. However with time multiple new inputs and outputs had to be added. Also because of the growing number of paramters that have been test some sort of log had to be created:
xlswrite('testfile.xlsx',[num2str(number), letter,num2str(number2x),next_letter],'append');
Also because the calculation takes a few hours and should run over night multiple parameter sets had to be started at one point. This is easily done with [x1,y1] = test(1,'a');[x2,y2] = test(2,'b'); in one line or adding new tasks while the old still run. However this way you can't keep track on how many are still open.
So in total I need some sort of testing framework, that can keep up with changeging inpus and outputs, keeps track on already doen calculations and ideally also handles the open runs.
I feel like i can't be the only one who faces this issue, in fact I think so many people face this issue that Mathworks would already came up with a solution.
For Simulink this has been done in form of a Simluationmanager, but for Matlab functions the closest thing i found is the Testing framework (example below) which seems to be rather for software development and debugging and not at all for what i am trying. And somepoint there seem to be 3rd party solutions but they are no longer continued in favor of this Testing framework.
function solutions = sampleTest
solutions = functiontests({#paramtertest});
end
function paramtertest(vargin)
test(1,'a');
test(2,'b');
end
function [number2x,next_letter] = test(number, letter)
number2x = number * 2;
next_letter = letter + 1;
disp(['next letter is ' next_letter])
disp(['number times 2 is ' num2str(number2x)])
xlswrite('testfile.xlsx',[num2str(number), letter,num2str(number2x),next_letter],'append');
end
Alternatively I could create my test as a class, create an interface similar to the Simulationmanager, create numerous functions for managing inputs and outputs and visualize the progress and then spawn multiple instances of if i want to set up a new set of parameters while already running a simulation. Possible, yet a lot of work that does not involve the simulation directly.
In total following questions arise:
Is there a build in Matlab function for managing simulations that i totally missed so far?
Can the the Testing framework be used for this purpose?
Is there already some Framework (not from Mathworks) that can handle this?
If i create my own class, could multiple instances run individually and keep track of their own progress? And would those be handled simultaniously or would matlab end up running the in the order they started?
I know this question is somewhat in the off-topic: recommend or find a tool, library or favorite off-site resource area. If you feel it is too much so, please focus on the last question.
Thank you!
I've done similar tests using GUI elements. Basic part of simulation was inside while loop, for example in your case:
iter = 0;
iter_max = 5; %the number of your times, you will call script
accu_step = 2; %the accuracy of stored data
Alphabet = 'abcdefghijklmnopqrstuvwxyz'
while iter < iter_max
iter = iter+1;
[x1,y1] = test(i,Alphabet(i));
end
Now you should create a handle to progress bar inside your computation script. It will show you both on which step you are, and the progress of current step.
global h;
global iter_opt;
if isempty(h)
h=waitbar(0,'Solving...');
else
waitbar(t/t_end,h,sprintf('Solving... current step is:%d',iter));
end
You didn't specified which function you use, if it is for example time-depended the above t/t_end example is an estimation of current progress.
The solving of result also require to be changed on every execution of loop, for example:
global iter;
i_line = (t_end/accu_step+2)*(iter-1);
xlswrite('results.xlsx',{'ITERATION ', iter},sheet,strcat('A',num2str(i_line+5)))
xlswrite('results.xlsx',results_matrix(1:6),sheet,strcat('D',num2str(i_line+5)))
The above example were also with assumption that your results are time-related, so you store data every 2 units of time (day, hours, min, what you need), from t_0 to t_end, with additional 2 rows of separation, between steps. The number of columns is just exemplary, you can adjust it to your needs.
After the calculation is done, you can close waitbar with:
global h
close(h)
I have a code that goes like this which I want to run using parpool:
result = zeros(J,K)
for k = 1:K
for j = 1:J
build(:,1) = old1(:,j,k)
build(:,2) = old2(:,j,k)
result(j,k) = call_function(build); %Takes a long time to run
end
end
It takes a long time to run this code and I have to run this multiple times for my simulation so I want to run the outermost loop (k = 1:K) in parallel in MATLAB.
From what I have read, I cannot use parfor since all each function uses the same variables old1 and old2. I could use spmd and distribute my matrices old1 and old2. But I read this creates as many copies of the variable as the workers and I do not want this to happen. I could use drange. But I am not sure how it exactly works. I am finding it difficult to actually use what I have been reading in MATLAB references. Any resource and pointers would be of great help!
Constraints are as follows:
Must not create multiple copies of the variables old1, old2. But I can slice it across workers as each iteration doesn't require other iterations.
Have to distribute for the outermost loop only. For ease of accessing data outside this block of code.
Thank you.
old1 and old2 can be used, I think. Initialize as constants using:
old1 = parallel.pool.Constant(old1);
old2 = parallel.pool.Constant(old2);
Have you seen this post?
https://www.mathworks.com/help/distcomp/improve-parfor-performance.html
I am running a for loop where I compute 3 variables separately and then add them all up in the end, i.e.
for time=0:endtime
calculate_a(a,u);
calculate_b(b,u);
calculate_c(c,u);
u=a+b+c;
end
I would like to parallelise this loop so that each calculation of a, b and c is done by an individual worker and they are all put together for u calculation, i.e.:
for time=0:endtime
calculate_a(a,u); % performed by worker 1
calculate_b(b,u); % performed by worker 2
calculate_c(c,u); % performed by worker 3
% all workers share their outcome and perform
u=a+b+c;
end
I am new to parallel computing in Matlab. Can you help me figure out how to go about this? Also, are there any problems in creating a stand-alone program (.exe) from Matlab when using parallel computing?
Many thanks!
Use createJob, createTask, submit, and fetchOutputs. The documentation is pretty clear but let me know if you need more help.
I have an algorithm myAlgo() which uses a parameter par1 in order to analyze a set of data (about 1000 .mat files). The path to the .mat files is some cell array I pass also to myAlgo(). The myAlgo() function contains classes and other functions. For every value of par1 I have to test all 1000 .mat files. So it would be a lot faster if I could use a parallel loop since I have an independent (?) problem.
I use the following code with parfor:
par1 = linespace(1,10,100);
myFiles % cell array with the .mat file location
myResult = zeros(length(par1),1);
parfor k=1:length(par1)
myPar = par1(k);
myResult(k) = myAlgo(myPar, myFiles);
end
% do something with myResult
.
function theResult = myAlgo(myPar, myFiles)
for ii=1:length(myFiles)
tempResult = initAlgo(myPar, myFiles(ii));
end
theResult = sum(tempResult);
end
So for every parameter in par1 I do the same thing. Unfortunately the processing time does not decrease. But if I check the workload of the CPU (i5), all cores are quiet active.
Now my question: Is it possible, that parfordoes not work in this case, because every worker initialized by parfor needs to access the folder with the 1000 .mat files. Therefore they can not do their job on the same time. Right? So is there a way handle this?
First of all, check if you've got a license for the parallel computing toolbox (PCT). If you do not have one, parfor will behave just like a normal for loop WITHOUT actually parallel processing (for compatibility reasons)..
Second, make sure to open a parpool first.
Another problem may be that you are using parallel processing for the outer loop with 100 iterations, but not for the larger inner loop with 1000 iterations. You should rephrase your problem as one big loop that allows parfor to parallelize the 100*1000=100000 tasks, not just the 100 outer loops. This excellent post explains the problem nicely and offers several solutions.
I have a linux cluster with Matlab & PCT installed (128 workers with Torque Manager), and I am looking for a good way to parallelize my calculations.
I have a time-series Trajectory data (100k x 2) matrix. I perform maximum likelihood (ML) calculations that involve matrix diagonalization, exponentiation & multiplications, which is running fast for smaller matrices. I divide the Trajectory data into small chunks and perform the calculations on many workers (coarse parallelization) and don't have any problems here as it works fine (gets done in ~30s)
But the calculations also depend on a number of parameters that I need to vary & test the effect on ML. (something akin to parameter sweep).
When I try to do this using a loop, the calculations becomes progressively very slow, for some reason I am unable to figure out.
%%%%%%% Pseudo- Code Example:
% a [100000x2], timeseries data
load trajectoryData
% p1,p2,p3,p4 are parameters
% but i want to do this over a multiple values fp3 & fp4 ;
paramsMat = [p1Vect; p2Vect;p3Vect ;p4Vect];
matlabpool start 128
[ML] = objfun([p1 p2 p3 p4],trajectoryData) % runs fast ~ <30s
%% NOTE: this runs progressively slow
for i = 1:length(paramsMat)
currentparams = paramsMat(i,:);
[ML] = objfun(currentparams,trajectoryData)
end
matlabpool close
The objFunc function is as follows:
% objFunc.m
[ML] = objFunc(Params, trajectoryData)
% b = 2 always
[a b] = size(trajectoryData) ;
% split into fragments of 1000 points (or any other way)
fragsMat = reshape(trajectoryData,1000, a*2/1000) ;
% simple parallelization. do the calculation on small chunks
parfor ix = 1: numFragments
% do heavy calculations
costVal(ix) = costValFrag;
end
% just an example;
ML = sum(costVal) ;
%%%%%%
Just a single calculation oddly takes ~30s (using the full cluster) but within the for loop, for some weird reason there is damping of speed & even within the 100th calculation, it becomes very slow. The workers are using only 10-20% of CPU.
If you have any suggestions including alternative parallelization suggestions it would be of immense help.
If I read this correctly, each parameter set is completely independent of all the others, and you have more parameter sets than you do workers.
The simple solution is to use a batch job instead of parfor.
job_manager = findresource( ... look up the args that fit your cluster ... )
job = createJob(job_manager);
for i = 1:num_param_sets
t = createTask(job, #your_function, 0, {your params});
end
submit(job);
This way you avoid any communications overhead you have from the parfor of the inner function, and you keep your matlabs separate. You can even tell it to automatically restart the workers between tasks (I think), as one of the job parameters.
What is the value of numFragments? If this is not always larger than your number of workers, then you will see things slowing down.
I would suggest trying to make your outer for loop be the parfor. It's generally better to apply the parallelism at the outermost level.