八度力深拷贝

Octave force deepcopy

问题

强制 Octave 创建任何对象的真实副本的方法有哪些?结构是主要兴趣。

我的潜在问题

在我的问题中,我在一个循环中从另一个函数获得了一个相当大的结构,但对于当前任务,只需要其中的几个部分。例如:

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

res 是一个相当大的数据块,由于延迟复制,那些 store-s 是对该块中一小部分字节的引用。在我存储这些小部分之后,我不需要 res 本身,但是,由于该块的中间部分被 store 引用,因此内存区域不适合下一个获得的 res迭代(它们具有相同的大小),因此分配了另一块相当大的内存,然后再次被一些小链接交叉等等。

在不存储部分 res 的情况下,程序成功地在前几次迭代后保持内存消耗不变。

那么如何制作结构字段的完整副本呢? 我试过使用 struct 相关的函数,例如 rmfield,但那些保留引用而不是它们自己的对象。 我试图将 的赋值包装在它自己的函数中: new_struct=复制(rmfield(old_struct,"bigdata")); 函数 c=复制(a); c=一个; 结尾; 顺便说一下,这甚至对数组也不起作用。 我对适用于任何通用变量的方法感兴趣。

问题的最小工作示例

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;

由于 a{i} 存储的引用阻塞了比实际需要更大的内存块,因此上述代码将导致内存使用量逐渐增长,远超过 whos 报告的 8.08 kb。如果强制正确复制,则问题不存在。

数值数组

对于数字类型,添加零足以保证一个新数组。

c=a+0;

字符串

对于 1 x n 字符数组的字符串,以下几行内容将起作用:

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

多维字符数组需要与列串联:

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

此处true用于生成大小与char兼容的虚拟数组。 (似乎没有生成任意大小的 char 数组的程序方法)char(zeros(size(a,1),1))char(true(size(a,1),1)) 在某些调用的创建过程中导致内存使用过多。

请注意,空连接 c=[a ""]; 不会导致复制。也可以执行 c=[a+0 ""]; ,这将导致由于 +0 而导致的复制,但是它会推断类型转换为 double 和从 double 转换,其大小​​是原来的 8 倍。 (char(zeros( 似乎不是这个原因)

其他类型

一般来说,您可以将 casting 用于它允许的类型,以免像我上面那样手动调整表达式:

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 似乎是 Octave 中可用的最小数据类型。 请注意,此方法不支持逻辑。

正在复制结构

显然,您必须编写自己的函数来遍历结构字段,使用上述方法复制它们并递归地转到子结构。
(因为它不涉及这里相关的复杂性,我宁愿让那些真正需要它的人来完成,我自己的问题由 +0 解决。)