我想知道是否有人对如何对以下循环进行矢量化有一个想法:
for i in range(1,(T*n)+1):
Y = Y + np.diag(mu) @ Y * dt + np.multiply(np.diag(sigma)@Y, L @ np.random.normal( 0, dt, (d,N)))
以下参数已经是dxN矩阵(我已经使用它对向量进行了矢量化。):
任何帮助将不胜感激。 :)
最诚挚的问候!
答案 0 :(得分:0)
不幸的是,这看起来不像可矢量化的代码:
迭代应该是独立的。通常,向量化意味着一次进行多次迭代。通常,这还意味着使用AVX,SSE或FMA指令(如果我们谈论x86处理器)可以使迭代真正在硬件级别上并行进行。
继续介绍矢量汇编指令,通常无法从python代码获得这种优化级别,因为解释器并不聪明。迭代也做得太多,无法向量化。它实际上包含子循环!我们看不到它,但是矩阵乘法确实涉及更多的循环。
因此,我不会将此循环的优化称为“向量化”。但幸运的是,仍然有一些事情需要检查:
配置文件。找出大部分时间都消耗在计算的哪一部分。
验证np.random
不会显着降低程序速度。如果是,则可以依靠预先生成的值。
检查可以向量化的代码 是否被向量化。这意味着,请验证您的numpy是否具有SSE / AVX支持,并且矩阵乘法是否已在后台使用。这样做可能有些棘手,但使用AVX最多可以达到x4的加速比。
如果确实在汇编级对部分代码进行了矢量化,则切换到将数据存储在float16数组中可以使其更快。据我所知,AVX确实支持对16位浮点数的大块进行操作。
用C / Cython重写它,或尝试Numba JIT编译完成同一任务。
如果即使使用Numba进行编译也不可行,我想知道Tensorflow是否可以在这里提供帮助。使用Tensorflow,Python代码不会立即启动计算,而是构造一个计算图,然后在不返回解释器级别的情况下执行该计算图。 Tensorflow确实支持AVX和SSE(尽管并非没有痛苦),因此与numpy相比,您可能期望对低级细节有更多的控制。您也可以尝试在GPU上启动它。
最后一点,我不太相信,但是循环展开帮助吗?
for i in range(1, (T * n + 1) // 4):
Y = Y + ...
Y = Y + ...
Y = Y + ...
Y = Y + ...
*-遵守阿姆达尔定律