Using Matlab Parfor with 'Eval' - matlab

I am trying to execute a parfor loop within a parent script for Matlab.
I want to calculate the implied volatility of an option price, and then create a new column within a preexisting dataset with the results.
load('/home/arreat/Casino/names.mat')
name = char(names(i))
%Loop over n rows to populate columns in dataset named using variable 'name(i)'
rows = eval(['length(',name,')'])
parfor n=[1:rows]
%Calculate implied volatility using blsimpv(Price, Strike, Rate, Time, Value, Limit,Yield, Tolerance, Class)
BidIV = blsimpv(eval([name,'.UnderlyingPrice(n)']),...
eval([name,'.Strike(n)']),...
RiskFree/100,...
eval([name,'.Lifespan(n)'])/252,...
eval([name,'.Bid(n)'])+.01,...
10,...
0,...
1e-15,...
eval([name,'.Type(n)'])...
)
eval([name,'.BidIV(n,1) = double(BidIV);']);
%Loop and add implied volatility (BidIV) to a column with n number of
%rows.
end
The problem arises with the 'eval()' calculation in the parfor loop. Mathworks suggested that I should turn the whole script into a function, and then call the function within the parfor loop.
While I work on this, any ideas?

Instead of calling eval all the time, you can call it once outside the loop, e.g. data = eval(name), and then use data.Strike etc inside the parfor loop.
To avoid calling eval at all, do the following:
%# load mat-file contents into structure allData, where
%# each variable becomes a field
allData = load('/home/arreat/Casino/names.mat');
data = allData.(name);

Related

Index increase in inner function

I have a main Matlab code which I use in order to calculate ode.
The main code contains many lines but I will explain only the ones needed.
The code looks as following (short version):
global array
t0=0
x0=[5,5]
dt=0.01
tfinal=10
[tout,xout]=rk4('equation',t0,x0,dt,tfinal) % the functions use the function 'equation' and calculates its values at every time from 0 to 20
Where 'equation' is another function from the following type:
global array
Dydx = equation(t,x)
Dydx=[x(1)
x(2)+array(j)]
j=j+1
However, as can be seen, inside the function "equation" there is a variable j which I want to increase every t iteration of rk4.
Which means that while I calculate the ode for time t, the rk4 should use function 'equation' and increase the j by one and so on.
The problem I get is that if I try to make 'equation' gives output of j like [Dydx,j] =equation(t,x) I recieve an error because of rk4.
How can I increase j in the inner function while the outside functions also get the value?(tried global but it kept showing j as [] in the work space).
I have tried to make it global as following but it didnt work:
global array jcount
t0=0
x0=[5,5]
dt=0.01
tfinal=10
jcount = 1;
[tout,xout]=rk4('equation',t0,x0,dt,tfinal)
global array jcount
Dydx = equation(t,x)
Dydx=[x(1)
x(2)+array(jcount)]
jcount=jcount+1
Thank you.
.

How to convert cell variable to classified variable inside of parfor loop in matlab? [duplicate]

I have this (quite long) Matlab code with nested loops where I want to parallelize the main time-consuming iteration. The only variable that (apparently) gives me problems is DMax, where I get the error:
Error: The variable DMax in a `parfor` cannot be classified.
See Parallel for Loops in MATLAB, "Overview".
This is a draft of my code:
t0=matrix (Maxiter,1); % This is a big matrix whose dimensions are reported in brachets
Maxiter = 1E6;
DMax = zeros(Maxiter,40);
% Other Stuff
for j=1:269
% Do more stuff
for soil=1:4
parfor i =1:Maxiter
k(i,soil) = a %k is a real number
a(i,soil) = b %similar to k
% Do a lot of stuff
for t= (floor(t0(i,soil))+1):40
DMax(i,t) = k(i,soil)*((t-t0(i,soil))^a(i,soil));
% Do some more stuff
end
end
end
end
for time=1:40
% Do the final stuff
end
I guess the problem is in the way I defined DMax, but I do not know what it could be more precisely. I already looked on the web but with not very satisfying results.
It is very clearly described in the documentation that each variable inside parfor must be classified into one of several types. Your DMax variable should be a sliced variable (arrays whose segments are operated on by different iterations of the loop), but in order to be classified as such, all the following conditions must hold:
Type of First-Level Indexing — The first level of indexing is either parentheses, (), or braces, {}.
Fixed Index Listing — Within the first-level parenthesis or braces, the list of indices is the same for all occurrences of a
given variable.
Form of Indexing — Within the list of indices for the variable, exactly one index involves the loop variable.
Shape of Array — The array maintains a constant shape. In assigning to a sliced variable, the right-hand side of the assignment cannot be [] or '', because these operators attempt to
delete elements.
Clearly, Fixed Index Listing property does not hold since you reference it as DMax(i,t) where t changes its values. There's an identical example described in the documentation, please pay attention. So one workaround would be to use a temporary variable inside the inner loop, and then assign the whole row back to DMax.
Also note that variable a cannot be classified into any category either. That's not to mention that it's not defined in your example at all. Please read the guide carefully and make sure it can be classified into one of the categories. Rewrite the code if needed, e.g. introducing new temporary variables.
Here's the code where DMax usage is corrected:
Maxiter = 1E6;
t0 = randn(Maxiter,1); % This is a big matrix whose dimensions are reported in brachets
DMax = zeros(Maxiter,40);
% Other Stuff
for j = 1:269
% Do more stuff
for soil = 1:4
parfor i = 1:Maxiter
k(i,soil) = a %k is a real number
a(i,soil) = b %similar to k
% Do a lot of stuff
tmp = zeros(1,40);
for t = (floor(t0(i,soil))+1):40
tmp(t) = k(i,soil)*((t-t0(i,soil))^a(i,soil));
% Do some more stuff
end
DMax(i,:) = tmp;
end
end
end
for time = 1:40
% Do the final stuff
end

Naming Image using index of for loop in each iteration

I am working in MATLAB for my image processing project.
I am using a for loop to generate some kind of image data (size of image varies) with each loop iteration. My problem is how do stop it from overwriting the image in next iteration.
Img(i,j)=data
Ideally I would like it to have
Img_1 = data (for 1st iteration)
Img_2 = data (for 2nd iteration)
Img_3 = data (for 3rd iteration)
and so on...
Is there any way, it can be acheived?
Yes, you can use dynamic field names with structures. I wouldn't recommend using separate variable names because your workspace will become unwieldy. Do something like this:
img_struct = struct(); %// Create empty structure
for ii = 1 : num_iterations
%// Do your processing on data
%...
%...
img_struct.(['Img_' num2str(ii)]) = data; %// After iteration
end
This will create a structure called img_struct where it will have fields that are named Img_1, Img_2, etc. To access a particular data from an iteration... say... iteration 1, do:
data = img_struct.Img_1;
Change the _1 to whatever iteration you choose.
Alternatively, you can use cell arrays... same line of thinking:
%// Create empty cell array
img_cell = cell(num_iterations, 1);
for ii = 1 : num_iterations
%// Do your processing on data
%...
%...
img_cell{ii} = data; %// After iteration
end
Cell arrays are arrays that take on any type per element - or they're non-homogeneous arrays. This means that each element can be whatever you want. As such, because your image data varies in size at each iteration, this will do very nicely. To access data at any iteration, simply do:
data = img_cell{ii};
ii is the index of the iteration you want to access.
If you want to literally obtain what you are asking for, you can use the eval() function, which takes a string as input that it will evaluate as if it were a line of code. Example:
for i=1:3
data=ones(i); % assign data, 'ones(i)' used as dummy for test
eval(['Img_' num2str(i) '=data;'])
end
However, I would recommend using cell arrays {}, or alternatively the struct function that rayryeng both suggested.

How does function work regarding to the memory usage?

When you are using function in MATLAB you have just the output of the function in the work space and all the other variables that maybe created or used in the body of that function are not shown. I am wondering how does function work? Does it clear all other variables from memory and just save the output?
function acts like a small, isolated programming environment. At the front end you insert your input (e.g. variables, strings, name-value pairs etc). After the function has finished, only the output is available, discarding all temporarily created variables.
function [SUM] = MySum(A)
for ii = 1:length(A)-1
SUM(ii) = A(ii)+A(ii+1);
kk(ii) = ii;
end
end
>> A=1:10
>> MySum(A)
This code just adds two consecutive values for the input array A. Note that the iteration number, stored in kk, is not output and is thus discarded after the function has completed. In MATLAB kk(ii) = ii; will be underlined orange, since it 'might be unused'.
Say you want to also retain kk, just add it to the function outputs:
function [SUM,kk] = MySum(A)
and keep the rest the same.
If you have large variables that you only use up to a certain point and wish them not clogging up your memory whilst the function is running, use clear for that:
function [SUM] = MySum(A)
for ii = 1:length(A)-1
SUM(ii) = A(ii)+A(ii+1);
kk(ii) = ii;
end
clear kk
end

MATLAB Return value of first non-empty argument (built-in COALESCE function)

Is there something inbuilt in MATLAB which functions similar to the SQL COALESCE function. I want that function to return the first 'existing' value from all the arguments.
For example,
clear A B; C=10; COALESCE(A,B,C)
should return value of C (because A and B are unassigned/don't exist).
I know it would be very easy to code, and I am just being lazy here. But, I would be surprised if MATLAB doesn't have a similar function.
As far as I know there is no built-in function for that. But you can easily write your own.
Note that it is not possible in Matlab to pass a variable that has not been defined prior of using it. Therefore your proposed call clear A B; C=10; COALESCE(A,B,C) is invalid and will throw an error. Instead we can define an empty variable using var=[].
The following code creates two empty variables A, B and and assigns C=10. Inside the function coalesce we assume at the beginning that all variables are empty. In the for-loop we return the first non-empty variable. In the version without for-loop we get the index of the first non-zero element and then return the corresponding content of the cell if a non-zero element exists.
If you want the function to be accessible from everywhere within Matlab, see the documentation here.
function testcoalesce
A = [];
B = [];
C = 10;
COALESCE(A,B)
COALESCE(A,B,C)
end
% with for-loop (much faster)
function out = COALESCE(varargin)
out = [];
for i = 1:length(varargin)
if ~isempty(varargin{i})
out = varargin{i};
return;
end
end
end
% without for-loop (slower)
function out = COALESCE(varargin)
out = [];
ind = find(cellfun('isempty', varargin)==0, 1);
if ~isempty(ind);
out = varargin{ind};
end
end
The output is as expected:
ans =
[]
ans =
10
Timing the two functions showed, that the first solution using the for-loop is approximately 48% faster than the function without loop.
(10 samples, 1'000'000 iterations, 3 variables & 20 variables)