为什么我们要使用向量化运算

问题背景

如果你是matlab用户,你一般都会使用向量化运算进行编程。原因也许很简单,因为matlab针对向量化运算在底层做了深度优化,尤其是针对矩阵乘法调用了MKL之类的高度优化的第三库来加速。所以我们在推演算法的阶段,尽量的以向量化,矩阵化,张量化的数学语言来描述算法,不仅仅是描述问题变得简单,更重要的是实现起来也比较容易。事实上还有另外一个原因,和代码本身是否经过深度优化无关。

问题分析

我们知道,程序代码运行的时间不仅仅和算法的计算复杂度有关,还和内存读写有莫大的关系。我们把它们表示为两部分t_1t2,如果你的软件系统有m次的内存读写,每次读写内存的平均时间为t_m;还有n次在执行真正的计算,每一次实施计算的平均时间为t_c,则有:

\begin{aligned} T_{total\_time} &= t_1 + t_2\\ &= m \,t_m+ n \,t_c\\ &=n\,t_c(1 + \frac{m}{n} \cdot \frac{t_m}{t_c})\\ &=n\,t_c(1 + \frac{1}{q} \cdot \frac{t_m}{t_c})\\ \qquad \text{ where } q &= \frac{n}{m} \end{aligned}

表示平均每读/写一次数据可以实施计算的次数,显然 q 这个值越大,该项任务的执行效率就越高。

常见向量化运算的q值

我们直接给出一个表格吧:

\begin{array}{|c|l|c|c|} \hline & n & m & q \\ \hline y=y+\alpha \, x & 2 N & 3N + 1 & 2/3 \\ \hline y = y + A x & 2N^2 & N^2+3N & 2 \\ \hline C = C + AB & 2N^3 & 4N^2 & N/2\\ \hline \end{array}

这里假设向量或矩阵的维度为N,我们发现只有矩阵乘法的q值和N有关,其它两种运算都是一个常数,其中标量乘法的运算效率是最低的。

结论

算法的实施采用矩阵语言描述不仅能使算法本身言简意赅,在真正实施计算的时候也是效率最高的,和是否使用了最优化的代码本身没有任何关系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在这段代码中,可以考虑使用量化运算来代替循环,从而提高代码的运行速度。下面是一些可能的优化方法: 1. 向量化计算点到钻孔的距离:使用矩阵运算代替循环计算点到钻孔的距离,可以显著提高代码的运行速度。例如,可以使用以下代码实现: ``` JSX = repmat(1:jx, jy, 1); % 生成从1到jx的矩阵 JSY = kron(1:jy, ones(1, jx)); % 生成从1到jy的矩阵 rr = sqrt((SLX - JSX).^2 + (SLY - JSY).^2); % 计算点到钻孔的距离 ``` 2. 向量化积分计算:对于积分计算,可以使用`integral2`函数进行向量化计算,从而避免循环计算。例如,可以使用以下代码实现: ``` [X, Y, Z] = meshgrid(a:dz:b, a:dz:b, 1:nj); % 计算积分区域 f1 = @(x, y, z) 0.25 * exp(v * Xt / Rap) .* exp(-v * sqrt(rr.^2 + (z - x).^2) / Rap) .* erfc((sqrt(rr.^2 + (z - x).^2) - v * t) / sqrt(Rap * t)) ./ sqrt(rr.^2 + (z - x).^2) / (2 * pi * Rlamd); f2 = @(x, y, z) 0.25 * exp(v * Xt / Rap) .* exp(v * sqrt(rr.^2 + (z - x).^2) / Rap) .* erfc((sqrt(rr.^2 + (z - x).^2) + v * t) / sqrt(Rap * t)) ./ sqrt(rr.^2 + (z - x).^2) / (2 * pi * Rlamd); f3 = @(x, y, z) 0.25 * exp(v * Xt / Iap) .* exp(-v * sqrt(rr.^2 + (z + x).^2) / Iap) .* erfc((sqrt(rr.^2 + (z + x).^2) - v * t) / sqrt(Iap * t)) ./ sqrt(rr.^2 + (z + x).^2) / (2 * pi * Ilamd); f4 = @(x, y, z) 0.25 * exp(v * Xt / Iap) .* exp(v * sqrt(rr.^2 + (z + x).^2) / Iap) .* erfc((sqrt(rr.^2 + (z + x).^2) + v * t) / sqrt(Iap * t)) ./ sqrt(rr.^2 + (z + x).^2) / (2 * pi * Ilamd); % 计算积分值 aa = integral3(f1, a, b, a, b, 1, nj); ab = integral3(f2, a, b, a, b, 1, nj); ac = integral3(f3, a, b, a, b, 1, nj); ad = integral3(f4, a, b, a, b, 1, nj); ``` 这样可以避免循环计算,从而提高代码的运行速度。 需要注意的是,向量化运算并不是在所有情况下都能提高代码的运行速度。一些情况下,循环计算可能比向量化运算更快,具体的优化方法需要根据具体情况来选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值