Power by GeekHades

Matlab/Octave中元素点乘与For-Loop效率比较

前言

在Matlab/Octave等高级原型语言中,有以下两种方法可以完成对两个同型向量或矩阵对应元素运算:

  1. 使用For-Loop。
  2. 使用元素点乘。

对于方法一,是要编写循环逻辑的,直观上看起来会产生比较多的代码。 对于方法二,不需要开发者手动编写循环逻辑,代码非常简洁。

对于以上两种方法,我们可以探讨一下在大量数据环境下,元素点乘和For-Loop这两种方式那种执行效率更高。

PS:由于自己本身是传统程序员转型,所以习惯了For-Loop对元素迭代操作,然而对于点乘这种简洁的操作有时很难第一时间想到,所以纠结出了此文。

实验

实验方法:给定一个变量𝒙,𝒙可以是向量也可以是矩阵,进而计算Sigmoid(𝒙)函数的结果值。使用For-Loop、元素点乘以及半For-Loop半点乘的方式分别实现下面的Sigmoid函数:

Sigmoid(x) = \frac{1}{1 + e^{-x}}

数据集: 使用rand函数产生一个10^7 * 10的矩阵共计 1亿(10^8) 条数据项。

x = rand(1e7, 10);

For-Loop代码实现:

function g = TestForLoop(x)
% 对每一个元素进行迭代。

g = zeros(size(x));

id = tic;

[row, colums] = size(x);

for i = 1: colums

    for j = 1: row
        g(j, i) = 1 / (1 + e^(-z(j, i)) );
    end

end

toc (id)

end

元素点乘实现代码:

function g = TestDotMultiply(x)

g = zeros(size(x));

id = tic;

g = 1 ./ (1 + exp(-x) );

toc (id)

end

半For-Loop半点乘实现代码:

function g = TestSemiForLoop(x)
% 对每一列进行迭代计算。

g = zeros(size(x));

id = tic;

colums = size(x)(2);

for i = 1: colums

    g(:, i) = 1 ./ (1 + exp(-x(:, i) ) );

end

toc (id)

end

结果与总结

测试结果如下图所示,虽然没有多次测试取平均值,不过该结果也能说明问题。 result

  1. 纯For-Loop的迭代的结果很遗憾被我中断掉了,原因是因为运行时间超出了3min
  2. 纯元素点乘的形式其代码量非常的简洁,计算1亿条数据运行耗时大约在6s左右。
  3. 半For-Loop半元素点乘的形式展现的性能更是出乎意料,将矩阵分割为若干个列向量后计算性能将近节约一倍时间。

因此可以得出以下结论:

  • 从运行效率的角度来说:半For-Loop半元素点乘(分割矩阵形式)展现出来的性能是最优的。

  • 从代码量的角度来说:元素点乘产生的代码量极少,但不是那么容易一开始能得出运算公式。

最后祝大家学习进步、工作顺利、身体健康



* 如果你对文章有任何意见或建议请发 邮件 给我!
* if you have any suggestion that you could send a E-mail to me, Please!