八度力深拷贝
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
解决。)
问题
强制 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
解决。)