我有0-1值向量,我需要做一些矩阵运算.它们不是非常稀疏(只有一半的值为0)但是将它们保存为逻辑变量而不是双重保存8倍的内存:逻辑为1个字节,双浮点为8个字节. 逻辑矢量和双矩阵的
逻辑矢量和双矩阵的矩阵乘法比使用两者都慢吗?请参阅下面的初步结果:
>> x = [0 1 0 1 0 1 0 1]; A = rand(numel(x)); xl = logical(x); >> tic; for k = 1:10000; x * A * x'; end; toc %' Elapsed time is 0.017682 seconds. >> tic; for k = 1:10000; xl * A * xl'; end; toc %' Elapsed time is 0.026810 seconds. >> xs = sparse(x); >> tic; for k = 1:10000; xs * A * xs'; end; toc %' Elapsed time is 0.039566 seconds.
似乎使用逻辑表示要慢得多(稀疏甚至更慢).有人可以解释原因吗?是铸造时间吗?它是CPU / FPU指令集的限制吗?
编辑:我的系统是Mac OS X 10.8.3上的MATLAB R2012b,Intel Core i7 3.4 GHz
编辑2:一些评论表明,这只是Mac OS X的问题.如果可能,我想编译来自不同架构和操作系统的结果.
编辑3:我的实际问题需要使用长度为m的所有可能二进制向量的大部分进行计算,其中m对于8 * m * 2 ^ m而言可能太大以适合存储器.
我将首先发布一个略好的基准.我正在使用Steve Eddins的 TIMEIT功能来获得更准确的时间:function [t,err] = test_mat_mult() %# data N = 4000; sparsity = 0.7; %# adjust size and sparsity of data x = double(rand(1,N) > sparsity); xl = logical(x); xs = sparse(x); A = randn(N); %# functions f = cell(3,1); f{1} = @() mult_func(x,A); f{2} = @() mult_func(xl,A); f{3} = @() mult_func(xs,A); %# timeit t = cellfun(@timeit, f); %# check results v = cellfun(@feval, f, 'UniformOutput',true); err = max(abs(v-mean(v))); %# maximum error end function v = mult_func(x,A) v = x * A * x'; end
以下是我的机器上的结果(WinXP 32位,R2013a),N = 4000,稀疏度= 0.7:
>> [t,err] = test_mat_mult t = 0.031212 %# double 0.031970 %# logical 0.071998 %# sparse err = 7.9581e-13
您可以看到double仅比逻辑上的逻辑略好,而稀疏比预期的要慢(因为它的焦点是有效的内存使用而不是速度).
现在请注意,BLAS实现的MATLAB relies针对您的平台进行了优化,以执行full-matrix multiplication(想想DGEMM).在一般情况下,这包括单/双类型的例程,但不包括布尔值,因此将进行转换,这可以解释为什么它的逻辑性较慢.
在Intel处理器上,BL00 / LAPACK例程由Intel MKL Library提供.不确定AMD,但我认为它使用等效的ACML:
>> internal.matlab.language.versionPlugins.blas ans = Intel(R) Math Kernel Library Version 10.3.11 Product Build 20120606 for 32-bit applications
当然,稀疏案例是另一回事. (我知道MATLAB使用SuiteSparse程序包进行许多稀疏操作,但我不确定).