我正在使用Python的Anaconda发行版以及Numba,并且编写了以下Python函数,该函数将稀疏矩阵 A
(以CSR格式存储)乘以一个密集向量 x
:
@jit
def csrMult( x, Adata, Aindices, Aindptr, Ashape ):
numRowsA = Ashape[0]
Ax = numpy.zeros( numRowsA )
for i in range( numRowsA ):
Ax_i = 0.0
for dataIdx in range( Aindptr[i], Aindptr[i+1] ):
j = Aindices[dataIdx]
Ax_i += Adata[dataIdx] * x[j]
Ax[i] = Ax_i
return Ax
这 A
是一个大的scipy
稀疏矩阵,
>>> A.shape
( 56469, 39279 )
# having ~ 142,258,302 nonzero entries (so about 6.4% )
>>> type( A[0,0] )
dtype( 'float32' )
并且 x
是一个numpy
数组。这是调用上述功能的代码片段:
x = numpy.random.randn( A.shape[1] )
Ax = A.dot( x )
AxCheck = csrMult( x, A.data, A.indices, A.indptr, A.shape )
请注意, @jit
-decorator告诉Numba对 csrMult()
函数进行即时编译。
在我的实验中,我的功能csrMult()
大约是该方法的 两倍scipy
.dot()
。对于Numba来说,这是一个非常令人印象深刻的结果。
然而,MATLAB仍然执行有关此矩阵-向量乘法 6倍的速度
比csrMult()
。我相信这是因为MATLAB在执行稀疏矩阵向量乘法时会使用多线程。
for
使用Numba时如何并行化外循环?
Numba曾经有一个 prange()
函数,可以轻松地使尴尬的并行 for
循环并行化。不幸的是,Numba不再具有prange()
[ 实际上,这是错误的,请参见下面的编辑 ]。
那么,for
现在使Numbaprange()
函数消失的并行此循环的正确方法是什么?
当prange()
从Numba被删除,有什么其他没Numba的开发人员有什么想法?
编辑1:
我更新到Numba的最新版本,即0.35,prange()
现在又回来了!它没有包含在我一直使用的.33版本中。这是个好消息,但是不幸的是,当我尝试使用并行化我的for循环时,我收到一条错误消息
prange()
。这是Numba文档中的并行for循环示例(请参见第1.9.2节“显式并行循环”),以下是我的新代码:
from numba import njit, prange
@njit( parallel=True )
def csrMult_numba( x, Adata, Aindices, Aindptr, Ashape):
numRowsA = Ashape[0]
Ax = np.zeros( numRowsA )
for i in prange( numRowsA ):
Ax_i = 0.0
for dataIdx in range( Aindptr[i],Aindptr[i+1] ):
j = Aindices[dataIdx]
Ax_i += Adata[dataIdx] * x[j]
Ax[i] = Ax_i
return Ax
当我使用上面给出的代码片段调用此函数时,收到以下错误:
AttributeError:在nopython失败(转换为parfors)’SetItem’对象没有属性’get_targets’
以上使用prange
崩溃的尝试,我的问题是:
**并行化此Python 循环 的正确方法是什么 (使用prange
或替代方法) ? for
如下所述,在 20个* -omp-threads上运行时,并行化C ++中类似的for循环并获得 8倍的
加速是微不足道的。必须使用Numba进行处理,因为for循环令人尴尬地是并行的(并且稀疏矩阵向量乘法是科学计算中的基本运算)。 *
编辑2:
这是我的C 版本csrMult()
。for()
在我的测试中,并行执行C
版本中的循环可使代码快8倍。这向我暗示,使用Numba时,Python版本应该可以实现类似的加速。
void csrMult(VectorXd& Ax, VectorXd& x, vector<double>& Adata, vector<int>& Aindices, vector<int>& Aindptr)
{
// This code assumes that the size of Ax is numRowsA.
#pragma omp parallel num_threads(20)
{
#pragma omp for schedule(dynamic,590)
for (int i = 0; i < Ax.size(); i++)
{
double Ax_i = 0.0;
for (int dataIdx = Aindptr[i]; dataIdx < Aindptr[i + 1]; dataIdx++)
{
Ax_i += Adata[dataIdx] * x[Aindices[dataIdx]];
}
Ax[i] = Ax_i;
}
}
}
Numba已更新, prange()
现在可以工作! (我正在回答自己的问题。)
日期为2017年12月12日的此博客文章讨论了Numba并行计算功能的改进。这是该博客的相关摘要:
很久以前(超过20个发行版!),Numba曾经支持惯用语来编写称为的并行for循环
prange()
。在2014年对代码库进行了重大重构之后,必须删除此功能,但自那以来,它一直是Numba最常请求的功能之一。英特尔开发人员将数组表达式并行化之后,他们意识到带回prange
是很容易的
使用Numba版本0.36.1,我可以for
使用以下简单代码并行化尴尬的parallel -loop:
@numba.jit(nopython=True, parallel=True)
def csrMult_parallel(x,Adata,Aindices,Aindptr,Ashape):
numRowsA = Ashape[0]
Ax = np.zeros(numRowsA)
for i in numba.prange(numRowsA):
Ax_i = 0.0
for dataIdx in range(Aindptr[i],Aindptr[i+1]):
j = Aindices[dataIdx]
Ax_i += Adata[dataIdx]*x[j]
Ax[i] = Ax_i
return Ax
在我的实验中,并行化for
-loop使该函数的执行速度比我在问题开头发布的版本快了八倍,该版本已经在使用Numba了,但尚未并行化。此外,在我的实验中,并行版本比Ax = A.dot(x)
使用scipy的稀疏矩阵矢量乘法函数的命令快大约5倍。 Numba压碎了scipy
,我终于有了一个python稀疏的矩阵向量乘法例程,它的 速度与MATLAB一样快 。
问题内容: 我刚接触Python,但仍处于学习曲线的艰难阶段。感谢您的任何评论。 我有一个很大的for循环要运行(在许多迭代中都很大),例如: 我虽然认为这将是一个如何并行化的常见问题,但在Google上搜索了数小时后,我使用“多重处理”模块找到了解决方案,如下所示: 当循环较小时,此方法有效。但是,如果循环很大,这确实很慢,或者如果循环太大,有时会发生内存错误。看来python会首先生成参数列表
是否有人有任何使用TBB有效并行std::分区的技巧?这已经完成了吗? 以下是我的想法: 如果数组很小,std::将其分区(串行)并返回 否则,使用自定义迭代器将数组视为2个交错数组(在缓存大小的块中交错) 为每对迭代器启动一个并行分区任务(递归到步骤1) 在两个分区/中间指针之间交换元素* 返回合并的分区/中间指针 *我希望在一般情况下,与数组的长度相比,或者与将数组划分为连续块时所需的交换相比
我想在Python2.7中并行化两个嵌套的for循环,但我自己没有成功。我不知道如何接近什么是并行化的定义。 总之,这里是单处理器代码:
本文向大家介绍如何在PowerShell foreach并行循环中使用PSCustomObject?,包括了如何在PowerShell foreach并行循环中使用PSCustomObject?的使用技巧和注意事项,需要的朋友参考一下 要在Foreach并行循环内使用PSCustomObject ,我们首先需要考虑如何在循环内使用变量。 因此,让我们看看是否可以在$out变量中存储或更改值。 示例
我正在做一些研究,并且是一个使用CUDA的初学者。我使用的语言是C和C++,与NVIDIA的CUDA兼容的基本语言。在过去的一周里,我一直试图通过将CUDA与C++代码集成来获得任何加速。 此外,CUDA的实现也比正常的非CUDA版本慢。 下面是我调用内核函数的函数。本质上,我将原来在这个函数中的计算移到了核函数中,以便将它并行化。//计算输入之间的距离void computeInput(int
我正在尝试使用Postman来验证API。我可以毫无问题地验证单个请求,并获得所需的输出。但是,我现在想进行负载测试,并运行相同的调用5次。 我尝试使用for和while循环,但是Postman给出了一个错误。