更快的方式通过空矩阵乘法initilize数组吗?
20视图(30天)
显示旧的评论
我偶然发现了奇怪的方式(在我看来),Matlab处理空矩阵。例如,如果两个空矩阵相乘的结果是:
零(0)* 0 (0,3)
ans =
0 0 0
0 0 0
0 0 0
现在,这已经让我惊讶不已,然而,一个快速搜索了我的链接
//www.tatmou.com/help/matlab/math/empty-matrices-scalars-and-vectors.html
,我得到了一个解释,为什么这是发生的有些扭曲的逻辑。
然而
以下的观察,我一点准备都没有。我问自己,如何高效的就是这种类型的乘法vs使用0 (n)功能,说为了初始化?我用时间来回答这个问题:
f = @ () 0 (1000)
时间(f)
ans =
0.0033
与:
g = @ () 0 (1000,0) * 0 (0, 1000)
时间(g)
ans =
9.2048 e-06
都有相同的结果1000 x1000零的矩阵类的“双”,但空矩阵乘法的~快350倍!(发生相似的结果使用tic和toc的和一个循环)
这怎么可能?“时间”或“抽搐,toc的虚张声势或我发现了一个更快的方式来初始化矩阵吗?
(这样做是与matlab的2012,在这个主题- 64机器上,intel-i5 650 3.2 ghz…)
我更仔细的观察这个特点,两种不同的电脑上测试相同(matlab版本尽管2012)一个代码,检查运行时对矩阵的大小n。这就是我得到的:
使用的代码生成这个时间和之前一样,但一个循环tic和toc将看起来一样。因此,对于小尺寸,0 (n)是类似的。然而,在n = 400有跳空矩阵乘法的性能。我用来生成的代码,情节是:
n =独特(圆(logspace (0, 4200)));
为k = 1:长度(n)
f = @ () 0 (n (k));
时间t1 (k) = (f);
g = @ () 0 (n (k), 0) * 0 (0 n (k));
t2时间(k) = (g);
结束
重对数(n, t1,“b”,n, t2,“r”);
传奇(“零(n)”,“零(n, 0) * 0 (0, n)”2);
包含(“矩阵大小(n)”);ylabel (的时间(秒));
你们看到什么类似的吗?
5个评论
接受的答案
每•艾萨克森
2013年1月6日
编辑:每•艾萨克森
2013年1月6日
…我去了
链接
以上……
我不能找到你参考的链接。
。
Windows任务管理器显示
Z = 0 (1000,0) * 0 (0, 1000);
不分配内存(涉及R2012a、64位)。或者说任务管理器不显示任何分配的内存分配。
。
添加
我学会了两件事。有一个小的速度优势使用这种内存分配的方法。在试验我有必要重新启动计算机,我失去了我的桌面配置。
N = 1 e4;
清晰的z1
抽搐
z1 = 0 (N);
为cc = 1: N
z1 (:, cc) = cc;
结束
toc
清晰的z0
抽搐
z0 = 0 (N, 0) * 0 (0, N);
为cc = 1: N
z0 (:, cc) = cc;
结束
toc
运行时间是0.686084秒。
运行时间是0.532437秒。
3评论
更多的答案(4)
詹姆斯Tursa
2013年1月7日
编辑:詹姆斯Tursa
2013年1月7日
另一个(可能相关的)观察是MATLAB做一些pre 0填充背景的墨西哥人例程。例如,我运行下面的测试:
——通过mxMalloc分配一块很大的内存
——与非0的数据填补这一块
——还记得块地址
——自由与mxFree块
,立即再次与mxMalloc分配另一个非常大的块
——检查地址和内容
我发现第二个mxMalloc调用,返回相同的地址作为第一个电话,结果在数据块被设置为0。
这是设置数据块为0在后台调用mxFree和mxMalloc之间。如果一个定时的墨西哥人的例程可以探测到的努力为零的数据块的背景。但如果m文件层面上也有类似的事情发生(例如,有一个pre-0-filled数据块可供分配)它可能很难检测在计时。如果整件事是在一个循环中也许认为时机优势只会消失(如马特的例子)。
编辑
完成我对这个线程的墨西哥人相关的评论,我将提到有一个无证API调用“快0”函数mxFastZeros显然吸引了从以前分配内存并“0”了内存块,因为它非常快,可比时机0 (m, 0) * 0 (0, n)方法(我所知道的这种方法可能在后台调用mxFastZeros)。基本的墨西哥人程序实现如下:
/ / mxFastZeros。c生成一个零2 d双矩阵
/ /语法:z = mxFastZeros (ComplexFlag, M, N)
/ /地点:
/ / ComplexFlag = 0(真正的)或1(复杂的)
/ / M =行大小
/ / N =列的大小
/ /程序员:詹姆斯Tursa
#包括“mex.h”
mxArray* mxFastZeros (mxComplexity ComplexFlag, mwSize m, mwSize n);
mxArray* mxCreateSharedDataCopy (mxArray * mx);
无效mexFunction (int nlhs mxArray * plhs [], int nrhs, const mxArray * prhs [])
{
mxArray * mx;
mxComplexity ComplexFlag;
mwSize m, n;
如果(nrhs ! = 3) {
mexErrMsgTxt (“语法:mxFastZeros (ComplexFlag, M, N)”);
}
如果(nlhs > 1) {
mexErrMsgTxt (“太多的输出”。);
}
ComplexFlag = mxGetScalar (prhs [0]);
m = mxGetScalar (prhs [1]);
n = mxGetScalar (prhs [2]);
mx = mxFastZeros (ComplexFlag, m, n);
plhs [0] = mxCreateSharedDataCopy (mx);
mxDestroyArray (mx);
}
注意高级程序员:需要共享数据复制的东西因为mxFastZeros产生正常mxArray
(
不
在垃圾收集名单上),而不是一个临时mxArray
(
在
垃圾收集列表)记录API函数。使用mxCreateSharedDataCopy函数允许墨西哥人的例程返回一个临时mxArray和防止内存泄漏,会发生如果mxFastZeros的结果直接返回plhs [0]。
马特·J
2013年1月6日
编辑:马特·J
2013年1月6日
以下的观察,我一点准备都没有。我问自己,如何高效的就是这种类型的乘法vs使用0 (n)功能,说为了初始化?我用时间来回答这个问题:
你不能相信你所看到的是一个更有效的方法初始化(不幸的是)。这一切发生的是数组的实际创造被推迟到使用数组。你可以看到在下面的例子中,Z1需要更长的时间比Z2的总和,也因为它包含的实际实例化Z1出于某种原因。
N = 2000;
抽搐
Z1 = 0 (N, 0) * 0 (0, N);
toc%运行时间是0.000037秒。
抽搐
总和(Z1);
toc运行时间是0.008581秒。
抽搐;
Z2 = 0 (N);
toc%运行时间是0.007404秒。
抽搐
总和(Z2);
toc%运行时间是0.002177秒。