I have a MATLAB script running two copies of the same function and I want to run them in parallel on two different cores.
This is the function I am calling
function [outputVector] = ParallelPitchShift(inputVector, windowSize, hopSize, step)
%% Parameters
% Window size
winSize = windowSize;
% Space between windows
hop = hopSize;
% Pitch scaling factor
alpha = 2^(step/12);
% Intermediate constants
hopOut = round(alpha*hop);
% Hanning window for overlap-add
wn = hann(winSize*2+1);
wn = wn(2:2:end);
%% Source file
x = inputVector;
% Rotate if needed
if size(x,1) < size(x,2)
x = transpose(x);
end
x = [zeros(hop*3,1) ; x];
%% Initialization
% Create a frame matrix for the current input
[y,numberFramesInput] = createFrames(x,hop,winSize);
% Create a frame matrix to receive processed frames
numberFramesOutput = numberFramesInput;
outputy = zeros(numberFramesOutput,winSize);
% Initialize cumulative phase
phaseCumulat开发者_如何转开发ive = 0;
% Initialize previous frame phase
previousPhase = 0;
for index=1:numberFramesInput
%% Analysis
% Get current frame to be processed
currentFrame = y(index,:);
% Window the frame
currentFrameWindowed = currentFrame .* wn' / sqrt(((winSize/hop)/2));
% Get the FFT
currentFrameWindowedFFT = fft(currentFrameWindowed);
% Get the magnitude
magFrame = abs((currentFrameWindowedFFT));
% Get the angle
phaseFrame = angle(currentFrameWindowedFFT);
%% Processing
% Get the phase difference
deltaPhi = phaseFrame - previousPhase;
previousPhase = phaseFrame;
% Remove the expected phase difference
deltaPhiPrime = deltaPhi - hop * 2*pi*(0:(winSize-1))/winSize;
% Map to -pi/pi range
deltaPhiPrimeMod = mod(deltaPhiPrime+pi, 2*pi) - pi;
% Get the true frequency
trueFreq = 2*pi*(0:(winSize-1))/winSize + deltaPhiPrimeMod/hop;
% Get the final phase
phaseCumulative = phaseCumulative + hopOut * trueFreq;
% Remove the 60 Hz noise. This is not done for now but could be
% achieved by setting some bins to zero.
%% Synthesis
% Get the magnitude
outputMag = magFrame;
% Produce output frame
outputFrame = real(ifft(outputMag .* exp(j*phaseCumulative)));
% Save frame that has been processed
outputy(index,:) = outputFrame .* wn' / sqrt(((winSize/hopOut)/2));
end
%% Finalize
% Overlap add in a vector
outputTimeStretched = fusionFrames(outputy,hopOut);
% Resample with linearinterpolation
outputTime = interp1((0:(length(outputTimeStretched)-1)),outputTimeStretched,(0:alpha:(length(outputTimeStretched)-1)),'linear');
% Return the result
outputVector = outputTime;
return
And this is what I am doing to call the function
clear
x = wavread('x2.wav');
y1 = ParallelPitchShift(x,1024,256,7);
y2 = ParallelPitchShift(x,1024,256,12);
output = x(1:417000)' + y1(1:417000) + y2(1:417000);
sound(x,44100)
pause
sound(output,44100)
Is it possible to do this? Please let me know Thanks!
I don't understand what you mean by two copies of the same function. Did you mean two different input arguments to the same function or that the two functions are completely different?
I'm assuming its the former (because that's what you've written). In that case, try
somethingVector=[something, something2];
parfor i=1:2
function(something(i),otherArgs)
end
Remember, before you use a parfor
loop, you should open a pool of workers like so:
matlabpool('open',2)
What you want is the Single Program Multiple Data, or spmd function from the Parallel Computing toolbox. From the documentation:
The spmd statement lets you define a block of code to run simultaneously on multiple labs.
To use it you first have to define a matlabpool.
matlabpool 3
This automatically creates a "hidden" variable in the workspace called labindex, which specifies which lab is currently doing the work.
labindex
ans =
1
When we use spmd we execute our code in parallel on all the labs opened by matlabpool.
spmd
labindex
end
Lab 1:
ans =
1
Lab 2:
ans =
2
Lab 3:
ans =
3
We can use labindex to specify different input to the same function and run everything in parallel. If we have two different matrices and want to find the eigenvalues in parallel we could do
M = {rand(10) rand(20)}; %Put matrices into cell for easy access
spmd
if labindex < 3 %We only have two matrices, so only need two labs
E = eig(M(labindex));
end
end
E
E =
Lab 1: class = double, size = [10 1]
Lab 2: class = double, size = [20 1]
Lab 3: No data
I've tested parallel toolbox and ended up not buying it specifically because you can not control what functions run on which core. So if you start up multiple workers (using matlabpool()
) and attempt to send the function processing to a specific worker/pool, it won't work. However using parfor
will distribute the workload evenly over the cores in order to optimize processing time.
For what I was trying to do, the solution was to have different sessions of matlab running. Hoping the CPU distributes the next session to another CPU
精彩评论