Dynamic variable names for full workspace operations
이전 댓글 표시
To start with, I understand dynamic variable names are bad. I am not really trying to use them. What I really want to do is apply a specific operation to all variables in the current workspace; this way I can generate a generic function to apply that operation.
Two examples: Example 1
Let's say that I have a code where I can use double or single precision depending on user choice. I want to cycle through all of the workspace variables looking for e.g. doubles that have numel>1000 and convert all of them to single. I can use who to get my workspace, and then a loop with isa and a boolean to find all the variables that match those criteria. What I want to do now is perform the operation varname = single(varname) to reassign those variables to the single-precision class while keeping the same name. Is there a way to do this other than using dynamic variable names?
Example 2
Lets say I ran into an "out-of-memory" error on the GPU because there is a bunch of junk left on there from other operations. I want to cycle through all gpuArray class variables and pull them down using varname = gather(varname), perform a reset(gpuDevice), and then possibly place them back on the gpu using varname = gpuArray(varname). Again, I understand that I could write a code that knows all of the variable names, the point here is to generate a generic code that can do the operation on all the correct workplace variables.
Again, if there is a totally obvious way of doing this that doesn't involve dynamic names, please let me know. Also, if there is something super bad about either of these concepts, I need to know that too.
Otherwise...how do you code something like this using dynamic variable names, since Matlab seems to make that kind of operation intentionally difficult.
Thanks for your help, -Dan
댓글 수: 4
the cyclist
2017년 2월 1일
편집: the cyclist
2017년 2월 1일
I'll be interested to hear what the more knowledgeable folks around here have to say. Your examples seems to be a form of metaprogramming, as you are writing code that will write code, and avoiding eval() in these cases is challenging.
(I'm mostly leaving this comment as a way of "following" your question.)
"...can use double or single precision depending on user choice. I want to cycle through all of the workspace variables"
"Is there a way to do this other than using dynamic variable names?"
How did these variables get into the workspace?
Did you type them all? Likely no. Which means they were imported somehow, or are defined in the functions themselves.
If they are imported using load or any file reading function then there is absolutely no reason why there needs to be a workspace full of variables: simply import into one array, cell, structure, table, etc and then your task is trivial (one line, no eval).
And if they are there because you are running a user's script then run for the hills screaming. So you sensibly have functions, and are not doing absurd things with load or assignin or the like. Then there is no way you cannot have total control over how those variables get into the function workspace (at generation or import). Most likely you could split the code into sub-functions, cells, loops, or whatever, which then allows easy points to check the values and adjust the data class as you require. Thus your entire question becomes moot.
Even though you have written "I understand dynamic variable names are bad" it seems you have not realized that you can fix the problem at its source, not by trying to patch it up later.
"totally obvious way of doing this that doesn't involve dynamic names"
Yeah, don't have lots of variables. Pretty simple really.
James Tursa
2017년 2월 4일
편집: James Tursa
2017년 2월 4일
For re-classing variables from double to single, I will mention that this will have issues if any of the variables are shared copies of other variables. A loop that does varname = single(varname) will effectively unshare the variables which would have negative memory usage consequences. E.g., a simplistic example:
X = a 1GB double array
Y = X; % a shared data copy of X.
At this point you only have 1GB of data in memory, since both X and Y are sharing data. Now see what happens when you make each of them single class:
X = single(X): % X is unshared with Y and turned into single
Y = single(Y); % Y is turned into single
After the 1st statement, total data memory is 1.5GB. After the 2nd statement, total data memory is back down to 1GB. But X and Y are not shared copies of each other any more, so there is no memory sharing benefit as was the case in the beginning. Ideally, if one knows that X and Y are shared, you would like to do something like this instead to get the total data memory down to 0.5GB:
X = single(X);
Y = X;
But there are no official mechanisms for detecting variable sharing status, either at the m-file level or in a mex routine. The only way to detect sharing is to hack into the variables in a mex routine, and even then it can get messy very quickly if there are cell arrays, struct arrays, or classdef objects involved.
Bottom line is that if there is a significant amount of data sharing involved, re-classing variables serially will wipe that sharing out and have negative memory usage consequences.
D. Plotnick
2017년 2월 10일
채택된 답변
추가 답변 (2개)
Edric Ellis
2017년 2월 2일
For the gpuArray case, you could simply use save and load, i.e.
tempFile = tempname();
save(tempFile);
reset(gpuDevice);
load(tempFile);
delete(tempFile);
댓글 수: 2
D. Plotnick
2017년 2월 3일
Walter Roberson
2017년 2월 3일
I did some poking around and thought I was getting somewhere but it didn't work. I was looking for a way to get at the workspace of the current function, with the idea that altering the workspace would be equivalent to altering the variable. I found that if you declare a nested function and use functions() that you get a workspace of the nested function that includes all variables in the parent assigned at the point you took the handle, which seemed like a doable way of getting access to your own workspace. Unfortunately changing the workspace did not change the variables in the function even for the shared variables. I was not able to get further on this.
It did leave me wondering if it would work for moving values in and out of the GPU array. If you have a shared variable that is assigned a gpu array and you gather it and send it again, then does that affect the original gpu array? The gather is going bring it back clearly, but the rewrite might instead create a second variable. I consider evalin('caller') to be a form of eval() though others might disagree I guess.
Joss Knight
2017년 2월 5일
편집: Joss Knight
2017년 2월 5일
0 개 추천
Well, if you're really serious about a tool for managing storage of GPU arrays, then you need a new class. This would be a numeric handle type that forwards all its functions to the underlying type, and adds all new objects to a static list. All functions run in a try...catch statement to catch parallel:gpu:array:OOM and, if triggered it calls a static utility function to gather the contents of the list back to the host and try again.
The only difficulty here is that you need to provide an implementation of every single method you want your new type to implement, i.e. every method of gpuArray (and a few more that aren't methods of gpuArray but are functions that can take gpuArray inputs). But that code could be autogenerated fairly easily.
댓글 수: 2
D. Plotnick
2017년 2월 10일
Joss Knight
2017년 2월 17일
편집: Joss Knight
2017년 2월 17일
It's just a boiler-plate method for any function, so, say, for plus:
function varargout = plus(varargin)
% This bit swaps out the custom-type arguments for
% their underlying gpuArray property
for i = 1:numel(varargin)
if (isa(varargin{i}, 'MyManagedGPUArrayType')
varargin{i} = varargin{i}.UnderlyingArrayProperty;
end
end
% Try at least twice
for i = 1:2
try
[varargout{1:nargout}] = plus(varargin{:});
catch me
if i == 2 || me.identifier ~= "parallel:gpu:array:OOM"
rethrow(me);
else
MyManagedGPUArrayType.doSomeGatheringToClawBackMemory();
continue;
end
end
break;
end
end
So you create some script that reads a long list of function and creates a file with all these forwarding methods in, substituting in the name of the function. Well, no, you'd create a utility function for most of this call-gather-call structure and have a much simpler repeated boiler-plate for each method.
카테고리
도움말 센터 및 File Exchange에서 Variables에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!