python - 并行化 numba 循环
问题描述
之前,我问了一个关于 Numba 无法并行化的相对简单循环的问题。结果证明,一个解决方案使所有循环都变得明确。
现在,我需要执行相同任务的更简单版本:我现在有数组alpha
和beta
分别具有形状(m,n)
,(b,m,n),
并且我想计算计算参数的 2D 切片的 Frobenius 乘积,并找到使该乘积最大化的 beta 切片。以前,有一个额外的、大的第一维度,alpha
所以我并行化了这个维度;现在我想在第一个维度上并行化,beta
因为当 b>1000 时计算变得昂贵。
如果我天真地修改适用于上一个问题的代码,我会得到:
@njit(parallel=True)
def parallel_value_numba(alpha,beta):
dot = np.zeros(beta.shape[0])
for i in prange(beta.shape[0]):
for j in prange(beta.shape[1]):
for k in prange(beta.shape[2]):
dot[i] += alpha[j,k]*beta[i, j, k]
index=np.argmax(dot)
value=dot[index]
return value,index
但 Numba 出于某种原因不喜欢这样并抱怨道:
numba.core.errors.LoweringError: Failed in nopython mode pipeline (step: nopython mode backend)
scalar type memoryview(float64, 2d, C) given for non scalar argument #3
所以相反,我尝试了
@njit(parallel=True)
def parallel_value_numba_2(alpha,beta):
product=np.multiply(alpha,beta)
dot1=np.sum(product,axis=2)
dot2=np.sum(dot1,axis=1)
index=np.argmax(dot2)
value=dot2[index]
return value,index
只要您在将其传递给函数之前进行广播,它就会编译alpha
,beta.shape
并且原则上 Numba 能够并行化 numpy 操作。但它运行得非常缓慢,比串行的纯 Python 代码慢得多
def einsum_value(alpha,beta):
dot=np.einsum('kl,jkl->j',alpha,beta)
index=np.argmax(dot)
value=dot[index]
return value,index
所以,我当前的工作代码使用了最后一个实现,但是这个函数仍然是运行时的瓶颈,我想加快它的速度。谁能说服 Numba 以可观的速度并行化此功能?
解决方案
这并不完全是解决方案的答案,但格式化评论更难。
Numba 根据传递给函数的参数生成不同的代码。例如,您的代码适用于以下示例:
>>> alpha = np.random.random((5, 4))
>>> beta = np.random.random((3, 5, 4))
>>> parallel_value_numba(alpha, beta)
(5.89447648574048, 0)
为了诊断问题,有必要有一个导致问题的特定参数值的示例。
阅读错误消息,您似乎正在传递一个memoryview
对象,但 Numba 可能不完全支持它。
作为旁注,您不需要prange
在每个循环中都使用。只要预期的迭代次数大于机器中的内核数,通常在外循环中使用它就足够了。
推荐阅读
- angular - Angular 12迁移问题错误NG6002:出现在AppModule的NgModule.imports中,但本身有错误
- python - Python XML to CSV 在第二个数据框中查找值并列出多个值
- r - 从 kable 表中删除斜体
- discord.js - 如何在 Discord.js v13 中删除斜杠命令
- twilio - 来自客户端 js 的 Twilio 传出事件
- javascript - 执行数学运算时使用哪个更好?
- javascript - 在 Service Worker 中从 HTTPS 导入模块
- python - 在python中多次分配给变量的地图对象上使用列表函数
- django - 用于多个域和同一站点的 Django 站点地图
- time-complexity - 分布式网络算法的时间复杂度