matlab中子系数的乘法似乎比它们从中得到的矩阵的乘法要慢得多。
>> m = rand(1e7, 40);
>> tic; m' * m; toc % (1)
Elapsed time is 0.245803 seconds.
>> tic; m(1:2.5e6, :)' * m(1:2.5e6, :); toc % (2)
Elapsed time is 1.810981 seconds.
>> tic; t = m(1:2.5e6, :); t' * t; toc % (3)
Elapsed time is 0.885764 seconds.
我原本希望有一些快速内置的方法,因为数据已经在内存中,但似乎没有办法阻止matlab制作中间副本。 (3)我们制作副本的速度更快但是很野心。
matlab中是否有任何技术可以在矩阵的子集上快速进行操作(例如,多重转换,转置)?
使用mex实现这一目标的唯一快捷方式是什么?
编辑:使用列主要数据可以全速提升速度(正如预期的那样),但在将子系统倍增时仍然会慢得多。
>> m = rand(40,1e7);
>> tic; m * m'; toc
Elapsed time is 0.251958 seconds.
>> tic; m(:, 1:2.5e6) * m(:, 1:2.5e6)'; toc
Elapsed time is 1.461321 seconds.
>> tic; s=m(:, 1:2.5e6); s * s'; toc
Elapsed time is 0.555667 seconds.
显然matlab在索引时会复制,但有没有办法防止这种情况(显然这样的乘法算法可以存在而不复制数据,我只想知道它是否可以在matlab中表达)。
答案 0 :(得分:2)
这是更多的测试结果。
已经测试了五种执行矩阵乘法的方法,其中3种涉及子矩阵。正如@Cris指出的那样,如果使用rand(1e7,40)
可能会有所不同,因此测试了另一整套。
已经使用10次重复循环和Profiler来提高准确性。测试了具有丰富RAM的i7。
% clear;clc;close all
A = rand(1e7, 40);
for ii = 1:10
m = A;
m(end) = m(end-1);
m' * m; % 1
n = m';
n * m; % 2
m(1:2.5e6, :)' * m(1:2.5e6, :); % 3
t = m(1:2.5e6, :);
t' * t; % 4
t2 = t';
t2 * t; % 5
clearvars -except A
end
clearvars A
B = rand(40, 1e7);
for ii = 1:10
m = B;
m(end) = m(end-1);
m * m'; % 1
n = m';
m * n; % 2
m(:,1:2.5e6) * m(:,1:2.5e6)'; % 3
t = m(:,1:2.5e6);
t * t'; % 4
t2 = t';
t * t2; % 5
clearvars -except B
end
40x2.5e6
显然更快。 m'*m
它识别模式并跳过转置操作。 答案 1 :(得分:1)
MATLAB执行写时复制,这意味着复制矩阵并不真正复制数据,至少在您尝试更改指向相同数据的两个矩阵之一之前。但是,复制矩阵的一部分时,始终会复制数据。也就是说,矩阵从不指向不同矩阵的值的子集。 MATLAB总是将数据连续存储在内存中(列主要排序),因此很少会出现您索引的矩阵部分在内存中连续的情况。尝试这一点的一种方法是使用format debug
并查看数据指针:
>> format debug
>> q=rand(10,100)
q =
Structure address = 127e64560
m = 10
n = 100
pr = 7f9f5c835420
pi = 0
Columns 1 through 9
0.8147 0.1576 0.6557 0.7060 0.4387 0.2760 0.7513 0.8407 0.3517
...
>> q(:,1:2)
ans =
Structure address = 11dadd750
m = 10
n = 2
pr = 7f9f5b792700
pi = 0
0.8147 0.1576
..
注意pr
值(指向数据的实值部分的指针)如何变化。这表明数据已被复制。
如果你不能使用矢量化代码(即在矩阵上作为一个整体应用操作),加速计算的最佳选择是MEX文件。