简体   繁体   中英

Octave force deepcopy

The question

What are the ways of coercing octave to create a real copy of whatever object? Structures are the main interest.

My underlying problem

In my problem I'm obtaining a rather large structure from another function in a loop but for the current task only a few pieces of it are needed. For example:

for i=1:many
    res=solver(params);
    store1{i}=res.string1;
    store2{i}=res.arr(:,1);
end

res is a sizable chunk of data and due to lazy-copy those store -s are references to tiny portions of bytes in that chunk. After I store those tiny portions, I don't need res itself, however, since middle of that chunk is referenced by store , the memory area is unfit for res obtained on the next iteration (they are of the same size) and thus another sizable piece of memory is allocated, which is then again crossed by few tiny links an so on.

Without storing parts of res, the program successfully keeps the memory consumption same after first couple of iterations.

So how do I make a complete copy of structure field? I've tried using struct -related functions like rmfield but those keep references instead of their own objects. I've tried to wrap the assignment of in its own function: new_struct=copy( rmfield(old_struct,"bigdata")); function c=copy(a); c=a; end; This by the way doesn't work even for arrays. I'm interested in method applicable to any generic variable.

Minimal working example of the problem

a=cell(3,1); 
for i=1:length(a); 
    r=rand(100000,1000);
    a{i}=r(1:100,end);
    whos; fflush(stdout);
    pause(2); 
end;

The above code will cause memory usage to gradually grow by far more than 8.08 kb reported by whos due to references stored by a{i} blocking bigger memory block than they actually need. If you force the proper copy, the problem is not present.

Numerical arrays

For numeric types addition of zero is enough to warrant a new array.

c=a+0;

Strings

For string which is 1 xn char array, something along the following lines will work:

c=[a "a"](1:end-1);

Multidimensional char arrays will require concatenation with a column:

c=[a true(size(a,1),1)](:,1:end-1);  

Here true is used to generate dummy array of size compatible with char. (There seems to be no procedural method of generating char array of arbitrary size) char(zeros(size(a,1),1)) and char(true(size(a,1),1)) caused excess memory usage during their creation on some calls.

Note that empty concatenation c=[a ""]; will not result in a copying. Also it is possible to do c=[a+0 ""]; which will result in a copying due to +0 but that one infers type conversions to and from double which is 8 times larger in size. ( char(zeros( doesn't seem to cause that)

Other types

In general you can use casting for the types allowed by it in order to not tailor the expressions manually as I had to do above:

typelist={"double","single","char"}; %full list of supported types is available in the link
class_of_a = typelist{ isa(a,typelist) };
c=typecast( [typecast(a,'single'); single(1)] (1:end-1), class_of_a);

Single is seemingly smallest datatype available in octave. Note that logical is not supported by this method.

Copying structures

Apparently you'd have to write your own function to go around struct fields, copy them with above methods and recursively go to substructs.
(As it doesn't involve complexities relevant here, I'd rather leave that to be done by those who actually needs that, my own problem being solved by +0 's.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM