I have a couple questions regarding MATLAB workspaces:
When does MATLAB decide to change the workspace and what conditions prompt it?
Something strange is happening in the following example. I run it with a breakpoint at line 4, then step using F10 to watch the workspace variables. Clearly, I see that m is deleted within the first iteration of the inner loop, but somehow MATLAB still knows to go to the next iteration in the outer loop!
Example:
something = 2;
somethingelse = 3;
for m = 1 : something
for n = 1 : somethingelse
%do something
clearvars -except n something somethingelse % This clears m, but it still functions
end
end
The only thing I can think of is that MATLAB probably has not updated the memory locations given that the variable does not show on the list.
In MATLAB there are generally two types of workspaces: the base workspace and function workspaces. The base workspace is what you use when you enter commands at the command line, or when you run scripts (all of which share the base workspace). Conversely, each function has its own unique workspace. Unlike C or C++ (or a number of other languages) you don't have any scoping of variable within loops or conditional structures, just one unique workspace for each instance of a function.
The issue you're seeing in your example isn't really related to this, it's just an artifact of how for loops behave in MATLAB. Taken from the "Tips" section:
Avoid assigning a value to the index variable within the loop statements. The for statement overrides any changes made to index within the loop.
In other words, once an iteration of the loop completes and returns to the beginning, MATLAB ignores any changes to the loop variable and simply increments it to the next value.
If you'd like to learn more details about MATLAB workspaces and scoping, I'd check out these links:
Share Data Between Workspaces
Nested functions
Local functions
global variables
persistent variables
Function handles
Matlab changes workspace to the current scope.
You've only cleared the value of m within the scope of the second loop.
Try adding p = m+n after the clearvars command within the second loop. Since you've cleared m only within the scope of the n loop, you cannot use it. However, you did not remove m from the scope of the m loop.
Also, since the m for loop exists within the scope of your base workspace, you can clear m within the m for loop all you want, the loop will always have access to it. That's why, if you remove the clearvars line, when you return to the base workspace, you can see m and n equal to something and somethingelse respectively.
What I think you're looking for is a better explanation of Matlab's memory management, which you can find here: MATLAB's Garbage Collector?
Related
I want to run a parfor loop in MATLAB with following code
B=load('dataB.mat'); % B is a 1600*100 matrix stored as 'dataB.mat' in the local folder
simN=100;
cof=cell(1,simN);
se=cell(1,simN);
parfor s=1:simN
[estimates, SE]=fct(0.5,[0.1,0.8,10]',B(:,s));
cof{s}=estimates';
se{s}=SE';
end
However, the codes seem not work - there are no warnings, it is just running forever without any outputs - I terminate the loop and found it never entered into the function 'fct'. Any help would be appreciated on how to load external data like 'dataB.mat' in the parallel computing of MATLAB?
If I type this on my console:
rand(1600,100)
and then I save my current workspace as dataB.mat, this command:
B = load('dataB.mat');
will bring me a 1 by 1 struct containing ans field as a 1600x100 double matrix. So, since in each loop of your application you must extract a column of B before calling the function fct (the extracted column becomes the third argument of your call and it must be defined before passing it)... I'm wondering if you didn't check your B variable composition with a breakpoint before proceeding with the parfor loop.
Also, keep in mind that the first time you execute a parfor loop with a brand new Matlab instance, the Matlab engine must instantiate all the workers... and this may take very long time. Be patient and, eventually, run a second test to see if the problem persists once you are certain the workers have been instantiated.
If those aren't the causes of your issue, I suggest you to run a standard loop (for instead of parfor) and set a breakpoint into the first line of your iteration. This should help you spot the problem very quickly.
while using Matlab parfor I came across the following behaviour
parpool(2)
parfor j=1:100
v = j+1;
clear v
end
> Error in ==> parallel_function>make_general_channel/channel_general at 886
> Transparency violation error.
I looked into it, and indeed one is not allowed to use clear within parfor.
My question is why. v is created inside every specific worker, and so it does not interfere with other workers.
Matlab uses static code analyzer to understand how the body of parfor loop interacts with main workspace, i.e. which variables need to be transferred to workers and back. A number of functions, such as eval, evalc, evalin, assignin (with the workspace argument specified as 'caller'), load (unless the output is assigned to a variable), save and clear can modify workspace in ways that cannot be predicted by the static analyzer. There is no way to ensure integrity of the workspace when multiple workers are operating on it, and such functions are used.
Important thing to realize is that when you use a command syntax to invoke a function, such as clear v, the argument is passed as a string literal, meaning there is no way for the static analyzer to understand which variable you are trying to clear, hence no way to figure out the effect the command will have on the workspace.
As suggested in documentation, the workaround to free up most of the memory used by a variable inside parfor is: v = [];
When I am running a function, i do not get all variables out in
work-space. When i set breakpoints than only i am able to get
variables in workspace. Therefore, how to get variables out in workspace without setting breakpoint?
While the assignin trick is handy in certain situations, one should generally not make a habit of non-explicitly 'poofing' variables across namespaces. The more obvious first approach should be to specify outputs to your function, which is basic MATLAB syntax.
If you have a small number of outputs, you can specify them individually. For example:
function [c, d] = trialcode(a, b)
% Simple summation
c = a + b;
% Simple product
d = a * b;
end
If you have many outputs, once approach is to store the desired outputs into a structure or cell array so you are outputting a single variable rather than having to specify every output. Tweaking the above example:
function [output] = trialcode(a, b)
% Simple summation
output.c = a + b;
% Simple product
output.d = a * b;
end
You can use
assignin('base','variablename',value);
to write variables from your Function-Workspace to your base-workspace.
When you use breakpoints you get to see the Workspace of the function or script that the execution stopped at. You can also choose in your Editor which Workspace(stack) you want to see in the debug mode.
If you want to write your whole Function-Workspace into your base-workspace (which in the sense of encapsulation is not recommended) you can use
vars=whos;
for k=1:length(vars)
assignin('base', vars(k).name, eval(vars(k).name));
end
On Matlab, when i am using a "for...end" loop, the indexing variable still exists in my workspace after the loop have been fully executed. I would like it to be automatically deleted, since its not relevant anymore outside of the loop and that it pollutes the workspace.
For example, in the following code, the variable "i", still exists after the execution of the loop. Since it should be a local variable, I would like it to be deleted automatically without me having to do it explicitely.
List = [1 2 3 4] ;
for i = List
fprintf('value = %i\n', i) ;
end
% "i" still exists, while its outside of its context
clear i; % I would like to avoid doing this everytime I exit a for..end
I know it is more of an aesthetic issue than a bug, but for an easier understanding of the results of my program, I would like those "temporary" variables to disappear when I exit their contexts.
So far, I only was able to reduce the number of those temporary variables by reusing them.
Edit:
It seems that there is no real solution to automatically remove those "temporary" variables.
The closest ways to avoid having those variables are:
Avoiding loops
Make the loops in functions, the variables of the functions are local and won't get in the workspace.
If you REALLY want to make sure that some of your variables have limited scope, and you want to avoid calling clear, you can use nested functions. Note that this may not help with readability, and it is more typing than calling clear. However, it does make sure that the only variables in your main function workspace are the ones that you want/need to remain.
function doSomething
List = [1 2 3 4] ;
runLoopOnList()
%# some other code here
%# nested functions
function runLoopOnList
%# i, and any other variable defined here
%# will not appear in the workspace
%# in contrast, all variables in the workspace
%# are visible and can be changed by the nested function
%# If a nested function should assign a new important
%# variable in the main workspace, have it return
%# and output.
for i = List
fprintf('value = %i\n', i) ;
end
end %# nested function
end %# main function
Look ! No loop, no iteration variable !
fprintf('value = %i\n', List)
And, while I'm here, I disagree that your i is a temporary variable; you've put it in the workspace so it is, essentially, global. Put it in another context (e.g. inside a function) if you don't want it to 'pollute' the workspace.
And yes, I know that Matlab has a concept of global variables which is slightly different from workspace variables, but it's not quite relevant here.
For example in testinit.m I have the following
function [x, y, m] = testinit
x=4
y=3
m=2
When I run testinit in the console it correctly displays the value. However when I type x it says
error: 'x' undefined...
Just to add to the above answer, the reason you're getting this is because variables in a MatLab function are local variables, they are not passed to the workspace unless you use one of the functions in the above answer. You can read more about global and local variables here.
P.S If you wrote an m-file that is not a function, then the variables are global.
There's the assignin function (evalin is related). And also global.
The other answers are all possible solutions, but potentially more complicated than what you may be looking for. I think the first part of yuk's answer addresses the real problem you are having, but I think it deserves a more detailed explanation...
If you have a function that has output arguments, you need to actually capture those arguments in variables when you call the function. For example, if you typed this in the Command Window:
[x, y, m] = testinit;
Then you would have your three output values present for you to use. What you were probably doing was typing this:
testinit;
This would display the values (because you didn't end each line in the function with a semicolon to suppress displaying them), but it would not store them in variables in the Command Window for you to use later.
This is a result of how variables are stored in MATLAB, as described by the documentation on variable scope:
MATLAB stores variables in a part of memory called a workspace. The base workspace holds variables created during your interactive MATLAB session and also any variables created by running scripts. Variables created at the MATLAB command prompt can also be used by scripts without having to declare them as global.
Functions do not use the base workspace. Every function has its own function workspace. Each function workspace is kept separate from the base workspace and all other workspaces to protect the integrity of the data used by that function. Even subfunctions that are defined in the same file have a separate function workspace.
So, if you want to share variables between functions, the simplest way is to pass them back and forth via their input and output argument lists.
It should also be noted that the names you give variables in the output argument list of the function don't have to match the names of the variables you place those output values in. For example, given this function:
function [a, b, c] = testinit
a = 4;
b = 3;
c = 2;
You can make this call in the Command Window:
[x, y, m] = testinit;
And you will get x = 4, y = 3, and m = 2.
If you run [x, y, m] = testinit in the console you should get the variables. The output variables can have any allowed name, not necessary x, y and m.
In addition you should put ; after each variable assignment in the function to avoid their output to the console. You can control the console output while calling the function.
If you want simply initialize new variables just by typing testinit, use assignin as in #BenVoigt's answer.
assignin('base','x',4)
However, this is dangerous, since some variable may already exist in the calling environment and will be overwritten. You can avoid it adding EXIST tests (inside EVALIN):
function testinit
if ~evalin('base','exist(''x'',''var'')')
assignin('base','x',4)
end
if ~evalin('base','exist(''y'',''var'')')
assignin('base','y',3)
end
if ~evalin('base','exist(''m'',''var'')')
assignin('base','m',2)
end
You can also use 'caller' instead of 'base' if you plan to call the function from another function.
The variables are local to the function so you cannot access them from the command line. As #BenVoigt said, you can use asignin but it's very dirty, and I don't think that it's what you really want to do.
I advise you do go in debug mode
Add a break point or a keyboard to your function like that:
function [x, y, m] = testinit
x=4
y=3
m=2
keyboard
After execute your function, and the command line will remain in the environment of the function.
The usual >> kill be replaced by a K>>. At that point you can access all your local variables.
To quit the debug mode type dbquit, or press shift+F5