访问结构与 "loose" 变量所需的时间
time needed to access struct vs. "loose" variable
我对从 matlab 结构或 matlab 变量(任何数组)访问/重新分配变量的时间有疑问:
想象一下您有一个函数创建十个变量(不同维度和大小的数组)的场景。此函数在另一个需要生成这些变量的函数中被调用。
现在,因为从函数中获取十个变量看起来很乱,所以我考虑将这十个变量存储在一个结构中,并更改我的初始函数,使其只输出一个结构(具有十个字段)而不是十个变量.
因为时间对我来说很重要(它是脑电图实验的代码),我想确保结构方法不会变慢,所以我编写了以下测试函数。
function test_timingStructs
%% define struct
strct.a=1; strct.b=2; strct.c=3;
%% define "loose" variables
a = 1; b = 2; c = 3;
%% How many runs?
runs = 1000;
%% time access to struct
x = []; % empty variable
tic
for i=1:runs
x = strct.a; x = strct.b; x = strct.c;
end
t_struct = toc;
%% time access to "loose variables"
x = []; % empty variable
tic
for i=1:runs
x = a; x = b; x = c;
end
t_loose = toc;
%% Plot results
close all; figure;
bar(cat(2,t_struct,t_loose));
set(gca,'xticklabel', {'struct', 'loose variable'})
xlabel('variable type accessed', 'fontsize', 12)
ylabel(sprintf('time (ms) needed for %d accesses to 3 different variables', runs), 'fontsize', 12)
title('Access timing: struct vs "loose" variables', 'fontsize', 15)
end
根据结果,访问结构以获取字段值比仅访问变量要慢得多。我可以根据我所做的测试做出这个假设吗?
有没有另一种方法可以整齐地 "package" 这十个变量,而不会在我想访问它们时浪费时间?
理论上,是的,访问 struct
中的数据将比访问存储在变量中的数据慢。这只是更高级别数据类型产生的开销。
但是
在您的测试中,您仅测量两个数据结构中数据的访问时间。当您使用变量时,只需将一个变量分配给另一个变量只需很少的时间,因为 MATLAB 使用写时复制并且实际上不会在内存中复制数据直到它被修改 .
因此,您编写的测试对于确定使用 struct
的实际成本不是很有用,因为我确定您的函数会做 某事 与它收到的数据。一旦您修改了数据,MATLAB 就会复制数据并执行请求的操作。因此,要确定 struct
的性能损失是多少,您应该为您的实际函数而不是您正在使用的空操作函数计时。
稍微现实一点的测试
我在下面编写了一个测试,比较了 struct
和被调用函数修改和不修改数据的变量访问。
function timeaccess
sz = round(linspace(1, 200, 100));
[times1, times2, times3, times4] = deal(zeros(size(sz)));
for k = 1:numel(sz)
n = sz(k);
S = struct('a', rand(n), 'b', rand(n), 'c', rand(n));
times1(k) = timeit(@()access_struct(S));
S = struct('a', rand(n), 'b', rand(n), 'c', rand(n));
times2(k) = timeit(@()access_struct2(S));
a = rand(n); b = rand(n); c = rand(n);
times3(k) = timeit(@()access_vars(a, b, c));
a = rand(n); b = rand(n); c = rand(n);
times4(k) = timeit(@()access_vars2(a, b, c));
end
figure
hax1 = subplot(1,2,1);
ylabel('Execution Time (ms)')
xlabel('Size of Variables');
hold on
plot(sz, times2 * 1000, 'DisplayName', 'Struct w/o modification')
plot(sz, times4 * 1000, 'DisplayName', 'Variables w/o modification')
legend(findall(hax1, 'type', 'line'))
hax2 = subplot(1,2,2);
ylabel('Execution Time (ms)')
xlabel('Size of Variables');
hold on
plot(sz, times1 * 1000, 'DisplayName', 'Struct w modification')
plot(sz, times3 * 1000, 'DisplayName', 'Variables w modification')
legend(findall(hax2, 'type', 'line'))
saveas(gcf, 'data_manipulation.png')
legend()
end
function [a, b, c] = access_struct(S)
a = S.a + 1;
b = S.b + 2;
c = S.c + 3;
end
function [a, b, c] = access_struct2(S)
a = S.a;
b = S.b;
c = S.c;
end
function [d, e, f] = access_vars(a, b, c)
d = a + 1;
e = b + 1;
f = c + 1;
end
function [d, e, f] = access_vars2(a, b, c)
d = a;
e = b;
f = c;
end
结果
如您所见,struct
只是将一个变量赋值给另一个变量比较慢,但是只要我执行一个操作(这里我有一个非常简单的操作,即向每个变量添加一个常量), 访问时间的影响可以忽略不计。
总结
根据上面的测试,我认为对于您的用例,两者之间的时间差可以忽略不计。即使 struct
稍微慢一点,它也可能是一种更简洁的设计并导致代码更具可读性/可维护性,并且可能值得性能上的差异。
如果您非常关心性能,可能值得研究 C/C++ mex 函数来为您完成一些繁重的工作,或者切换到比 MATLAB 性能更高的语言。
我对从 matlab 结构或 matlab 变量(任何数组)访问/重新分配变量的时间有疑问:
想象一下您有一个函数创建十个变量(不同维度和大小的数组)的场景。此函数在另一个需要生成这些变量的函数中被调用。
现在,因为从函数中获取十个变量看起来很乱,所以我考虑将这十个变量存储在一个结构中,并更改我的初始函数,使其只输出一个结构(具有十个字段)而不是十个变量.
因为时间对我来说很重要(它是脑电图实验的代码),我想确保结构方法不会变慢,所以我编写了以下测试函数。
function test_timingStructs
%% define struct
strct.a=1; strct.b=2; strct.c=3;
%% define "loose" variables
a = 1; b = 2; c = 3;
%% How many runs?
runs = 1000;
%% time access to struct
x = []; % empty variable
tic
for i=1:runs
x = strct.a; x = strct.b; x = strct.c;
end
t_struct = toc;
%% time access to "loose variables"
x = []; % empty variable
tic
for i=1:runs
x = a; x = b; x = c;
end
t_loose = toc;
%% Plot results
close all; figure;
bar(cat(2,t_struct,t_loose));
set(gca,'xticklabel', {'struct', 'loose variable'})
xlabel('variable type accessed', 'fontsize', 12)
ylabel(sprintf('time (ms) needed for %d accesses to 3 different variables', runs), 'fontsize', 12)
title('Access timing: struct vs "loose" variables', 'fontsize', 15)
end
根据结果,访问结构以获取字段值比仅访问变量要慢得多。我可以根据我所做的测试做出这个假设吗?
有没有另一种方法可以整齐地 "package" 这十个变量,而不会在我想访问它们时浪费时间?
理论上,是的,访问 struct
中的数据将比访问存储在变量中的数据慢。这只是更高级别数据类型产生的开销。
但是
在您的测试中,您仅测量两个数据结构中数据的访问时间。当您使用变量时,只需将一个变量分配给另一个变量只需很少的时间,因为 MATLAB 使用写时复制并且实际上不会在内存中复制数据直到它被修改 .
因此,您编写的测试对于确定使用 struct
的实际成本不是很有用,因为我确定您的函数会做 某事 与它收到的数据。一旦您修改了数据,MATLAB 就会复制数据并执行请求的操作。因此,要确定 struct
的性能损失是多少,您应该为您的实际函数而不是您正在使用的空操作函数计时。
稍微现实一点的测试
我在下面编写了一个测试,比较了 struct
和被调用函数修改和不修改数据的变量访问。
function timeaccess
sz = round(linspace(1, 200, 100));
[times1, times2, times3, times4] = deal(zeros(size(sz)));
for k = 1:numel(sz)
n = sz(k);
S = struct('a', rand(n), 'b', rand(n), 'c', rand(n));
times1(k) = timeit(@()access_struct(S));
S = struct('a', rand(n), 'b', rand(n), 'c', rand(n));
times2(k) = timeit(@()access_struct2(S));
a = rand(n); b = rand(n); c = rand(n);
times3(k) = timeit(@()access_vars(a, b, c));
a = rand(n); b = rand(n); c = rand(n);
times4(k) = timeit(@()access_vars2(a, b, c));
end
figure
hax1 = subplot(1,2,1);
ylabel('Execution Time (ms)')
xlabel('Size of Variables');
hold on
plot(sz, times2 * 1000, 'DisplayName', 'Struct w/o modification')
plot(sz, times4 * 1000, 'DisplayName', 'Variables w/o modification')
legend(findall(hax1, 'type', 'line'))
hax2 = subplot(1,2,2);
ylabel('Execution Time (ms)')
xlabel('Size of Variables');
hold on
plot(sz, times1 * 1000, 'DisplayName', 'Struct w modification')
plot(sz, times3 * 1000, 'DisplayName', 'Variables w modification')
legend(findall(hax2, 'type', 'line'))
saveas(gcf, 'data_manipulation.png')
legend()
end
function [a, b, c] = access_struct(S)
a = S.a + 1;
b = S.b + 2;
c = S.c + 3;
end
function [a, b, c] = access_struct2(S)
a = S.a;
b = S.b;
c = S.c;
end
function [d, e, f] = access_vars(a, b, c)
d = a + 1;
e = b + 1;
f = c + 1;
end
function [d, e, f] = access_vars2(a, b, c)
d = a;
e = b;
f = c;
end
结果
如您所见,struct
只是将一个变量赋值给另一个变量比较慢,但是只要我执行一个操作(这里我有一个非常简单的操作,即向每个变量添加一个常量), 访问时间的影响可以忽略不计。
总结
根据上面的测试,我认为对于您的用例,两者之间的时间差可以忽略不计。即使 struct
稍微慢一点,它也可能是一种更简洁的设计并导致代码更具可读性/可维护性,并且可能值得性能上的差异。
如果您非常关心性能,可能值得研究 C/C++ mex 函数来为您完成一些繁重的工作,或者切换到比 MATLAB 性能更高的语言。