优化MATLAB代码指南
我注意到了很多关于MATLAB优化的个别问题,但没有一个很好的指南 常见问题:优化MATLAB代码指南,matlab,optimization,Matlab,Optimization,我注意到了很多关于MATLAB优化的个别问题,但没有一个很好的指南 常见问题: % Where x is 1:1000, draw vertical lines from 5 to 10. x_values = 1:1000; y1_values = ones(1, 1000) * 5; y2_values = ones(1, 1000) * 10; % Set x_plot_values to [1, 1, NaN, 2, 2, NaN, ...]; x_plot_values = zero
% Where x is 1:1000, draw vertical lines from 5 to 10.
x_values = 1:1000;
y1_values = ones(1, 1000) * 5;
y2_values = ones(1, 1000) * 10;
% Set x_plot_values to [1, 1, NaN, 2, 2, NaN, ...];
x_plot_values = zeros(1, length(x_values) * 3);
x_plot_values(1:3:end) = x_values;
x_plot_values(2:3:end) = x_values;
x_plot_values(3:3:end) = NaN;
% Set y_plot_values to [5, 10, NaN, 5, 10, NaN, ...];
y_plot_values = zeros(1, length(x_values) * 3);
y_plot_values(1:3:end) = y1_values;
y_plot_values(2:3:end) = y2_values;
y_plot_values(3:3:end) = NaN;
figure; plot(x_plot_values, y_plot_values);
- 为我优化这个代码
- 如何将其矢量化
tic
和toc
调用用于显示我在何处测量所用时间
预分配
在Matlab中预分配阵列的简单操作可以提供巨大的速度优势
tic;
for i = 1:100000
my_array(i) = 5 * i;
end
toc;
这需要47秒
这需要0.1018秒
添加一行代码47秒到0.1秒是一个惊人的改进。显然,在这个简单的示例中,您可以将其矢量化为my_array=5*1:100000
(这需要0.000423秒),但我试图表示不使用矢量化的更复杂的时间
我最近发现,零函数(以及其他性质相同的函数)在预分配时没有简单地将最后一个值设置为0那么快:
tic;
length = 100000;
my_array(length) = 0;
for i = 1:length
my_array(i) = 5 * i;
end
toc;
这需要0.0991秒
现在很明显,这个微小的差异并不能证明什么,但是你必须相信我,在一个大文件中,有许多这样的优化,差异变得更加明显
为什么这样做?
预分配方法分配一块内存供您使用。这个内存是连续的,可以被预取,就像C++或java中的数组一样。然而,如果您不预先分配,那么MATLAB将不得不动态地找到越来越多的内存供您使用。据我所知,这与Java ArrayList的行为不同,更像是一个LinkedList,数组的不同块在内存中被拆分
不仅当您向其写入数据时(47秒!)速度会变慢,而且从那时起每次访问时都会变慢。事实上,如果你绝对不能预先分配,那么在你开始使用之前,将你的矩阵复制到一个新的预先分配的矩阵中仍然是有用的
如果我不知道要分配多少空间怎么办?
这是一个常见的问题,有几种不同的解决方案:
.mat
文件或类似文件,以便以后可以快速读取tic;
length = 100000;
% Reverse the for-loop to start from the last element
for i = 1:length
complicated_structure = read_from_file(i);
end
toc;
这需要1.5分钟
这需要6秒
这显然不是完美的预分配,之后翻转阵列需要一点时间,但时间的改进不言而喻。我希望有人有一个更好的方法来做到这一点,但这是一个相当好的黑客在同一时间
数据结构
就内存使用而言,结构数组比数组数组数组差几个数量级:
% Array of Structs
a(1).a = 1;
a(1).b = 2;
a(2).a = 3;
a(2).b = 4;
使用624字节
% Struct of Arrays
a.a(1) = 1;
a.b(1) = 2;
a.a(2) = 3;
a.b(2) = 4;
使用384字节
% Struct of Arrays
a.a(1) = 1;
a.b(1) = 2;
a.a(2) = 3;
a.b(2) = 4;
正如您所看到的,即使在这个简单/小的示例中,结构数组也比数组的结构使用了更多的内存。此外,如果要打印数据,数组结构的格式更有用
每个结构都有一个大的头,正如您所看到的,一个结构数组多次重复这个头,其中数组的结构只有一个头,因此使用的空间更少。这种差异在较大的阵列中更为明显
文件读取
代码中的fread
(或任何系统调用)数量越少越好
tic;
for i = 1:100
fread(fid, 1, '*int32');
end
toc;
前面的代码比下面的代码慢得多:
tic;
fread(fid, 100, '*int32');
toc;
你可能认为这是显而易见的,但同样的原则也适用于更复杂的情况:
tic;
for i = 1:100
val1(i) = fread(fid, 1, '*float32');
val2(i) = fread(fid, 1, '*float32');
end
toc;
这个问题不再简单,因为在内存中,浮点数是这样表示的:
val1 val2 val1 val2 etc.
但是,您可以使用fread的skip
值来实现与前面相同的优化:
tic;
% Get the current position in the file
initial_position = ftell(fid);
% Read 100 float32 values, and skip 4 bytes after each one
val1 = fread(fid, 100, '*float32', 4);
% Set the file position back to the start (plus the size of the initial float32)
fseek(fid, position + 4, 'bof');
% Read 100 float32 values, and skip 4 bytes after each one
val2 = fread(fid, 100, '*float32', 4);
toc;
因此,该文件读取是使用两个fread
s而不是200来完成的,这是一个巨大的改进
函数调用
我最近编写了一些代码,这些代码使用了许多函数调用,所有函数调用都位于不同的文件中。假设有100个单独的文件,所有文件都互相调用。通过将此代码“内联”到一个函数中,我看到执行速度从9秒提高了20%
显然,您不会以牺牲可重用性为代价来实现这一点,但在我的例子中,函数是自动生成的
% Where x is 1:1000, draw vertical lines from 5 to 10.
x_values = 1:1000;
y1_values = ones(1, 1000) * 5;
y2_values = ones(1, 1000) * 10;
% Set x_plot_values to [1, 1, NaN, 2, 2, NaN, ...];
x_plot_values = zeros(1, length(x_values) * 3);
x_plot_values(1:3:end) = x_values;
x_plot_values(2:3:end) = x_values;
x_plot_values(3:3:end) = NaN;
% Set y_plot_values to [5, 10, NaN, 5, 10, NaN, ...];
y_plot_values = zeros(1, length(x_values) * 3);
y_plot_values(1:3:end) = y1_values;
y_plot_values(2:3:end) = y2_values;
y_plot_values(3:3:end) = NaN;
figure; plot(x_plot_values, y_plot_values);