numba - guvectorize 只比 jit 快一点

2024-01-06

我试图并行化在许多独立数据集上运行的蒙特卡罗模拟。我发现 numba 的并行 guvectorize 实现仅比 numba jit 实现快 30-40%。

我找到了这些(1 https://stackoverflow.com/questions/31101699/numba-guvectorize-is-very-slow-compared-to-jit, 2 https://stackoverflow.com/questions/35350689/numba-guvectorize-target-parallel-slower-than-target-cpu)Stackoverflow 上的类似主题,但它们并没有真正回答我的问题。在第一种情况下,由于回退到对象模式,实现速度变慢,而在第二种情况下,原始发布者没有正确使用 guvectorize - 这些问题都不适用于我的代码。

为了确保我的代码没有问题,我创建了这段非常简单的代码来比较 jit 和 guvectorize:

import timeit
import numpy as np
from numba import jit, guvectorize

#both functions take an (m x n) array as input, compute the row sum, and return the row sums in a (m x 1) array

@guvectorize(["void(float64[:], float64[:])"], "(n) -> ()", target="parallel", nopython=True)
def row_sum_gu(input, output) :
    output[0] = np.sum(input)

@jit(nopython=True)
def row_sum_jit(input_array, output_array) :
    m, n = input_array.shape
    for i in range(m) :
        output_array[i] = np.sum(input_array[i,:])

rows = int(64) #broadcasting (= supposed parallellization) dimension for guvectorize
columns = int(1e6)
input_array = np.ones((rows, columns))
output_array = np.zeros((rows))
output_array2 = np.zeros((rows))

#the first run includes the compile time
row_sum_jit(input_array, output_array)
row_sum_gu(input_array, output_array2)

#run each function 100 times and record the time
print("jit time:", timeit.timeit("row_sum_jit(input_array, output_array)", "from __main__ import row_sum_jit, input_array, output_array", number=100))
print("guvectorize time:", timeit.timeit("row_sum_gu(input_array, output_array2)", "from __main__ import row_sum_gu, input_array, output_array2", number=100))

这给了我以下输出(时间确实有所不同):

jit time: 12.04114792868495
guvectorize time: 5.415564753115177

因此,并行代码也仅仅快两倍(仅当行数是 CPU 核心数的整数倍时,否则性能优势就会减弱),即使它利用了所有 cpu 核心,而 jit 代码仅使用一个(使用 htop 进行验证)。

我在一台配备 4 个 AMD Opteron 6380 CPU(总共 64 个内核)、256 GB RAM 和 Red Hat 4.4.7-1 操作系统的机器上运行该程序。 我将 Anaconda 4.2.0 与 Python 3.5.2 和 Numba 0.26.0 结合使用。

我怎样才能进一步提高并行性能或者我做错了什么?

谢谢您的回答。


那是因为np.sum太简单了。使用 sum 处理数组不仅受到 CPU 的限制,还受到“内存访问”时间。所以投入更多的核心并不能解决问题much的差异(当然这取决于与 CPU 相关的内存访问速度)。

仅用于可视化np.sum是这样的(忽略除data):

def sum(data):
    sum_ = 0.
    data = data.ravel()
    for i in data.size:
        item = data[i]   # memory access (I/O bound)
        sum_ += item     # addition      (CPU bound)
    return sum

因此,如果大部分时间都花在访问内存上,那么如果将其并行化,您将不会看到任何真正的加速。但是,如果 CPU 密集型任务是瓶颈,那么使用更多内核将显着加快代码速度。

例如,如果您包含一些比加法慢的操作,您将看到更大的改进:

from math import sqrt
from numba import njit, jit, guvectorize
import timeit
import numpy as np

@njit
def square_sum(arr):
    a = 0.
    for i in range(arr.size):
        a = sqrt(a**2 + arr[i]**2)  # sqrt and square are cpu-intensive!
    return a

@guvectorize(["void(float64[:], float64[:])"], "(n) -> ()", target="parallel", nopython=True)
def row_sum_gu(input, output) :
    output[0] = square_sum(input)

@jit(nopython=True)
def row_sum_jit(input_array, output_array) :
    m, n = input_array.shape
    for i in range(m) :
        output_array[i] = square_sum(input_array[i,:])
    return output_array

I used IPythontimeit https://ipython.org/ipython-doc/3/interactive/magics.html#magic-timeit在这里,但它应该是等效的:

rows = int(64)
columns = int(1e6)

input_array = np.random.random((rows, columns))
output_array = np.zeros((rows))

# Warmup an check that they are equal 
np.testing.assert_equal(row_sum_jit(input_array, output_array), row_sum_gu(input_array, output_array2))
%timeit row_sum_jit(input_array, output_array.copy())  # 10 loops, best of 3: 130 ms per loop
%timeit row_sum_gu(input_array, output_array.copy())   # 10 loops, best of 3: 35.7 ms per loop

我只使用 4 个核心,因此这非常接近可能的加速极限!

请记住,并行计算只能显着加快计算速度如果作业受 CPU 限制.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

numba - guvectorize 只比 jit 快一点 的相关文章

随机推荐

  • Fortify 源分析器和 Apache Lenya

    我正在尝试将 Fortify 源代码分析器用于我学校的一个研究项目 以测试开源 Java Web 应用程序的安全性 我目前正在研究 Apache Lenya 我正在使用最新的稳定版本 Lenya v2 0 2 根目录下有一个文件名为buil
  • 使用 querySelectorAll 时,Typescript 对象可能为“null”.ts(2531)

    class Test state elements container null constructor container HTMLElement null options permet de prendre les options du
  • 在 C# 中将文本添加到文件的开头和结尾

    我有一个进程可以获取一系列 xml 文件 我将 xml 放在引号中的原因是文件中的文本没有根元素 这会导致 xml 无效 在我的处理中 我想纠正这个问题并打开每个文件 在每个文件的开头和结尾添加一个根节点 然后将其关闭 这是我的想法 但这涉
  • 使用私钥通过 VSCode 连接到主机

    我想连接到远程服务器 我知道用户名和主机名 而且我也有private key pem文件 如何使用 VSCode 连接到该虚拟机 我在互联网上的解决方案中遇到了这个错误 这是合理的 因为我还没有导入这个private key pem文件在任
  • 对于没有字段的构造函数,reallyUnsafePtrEquality#

    据我了解 没有字段的类型的构造函数是 静态分配 的 并且 GHC在所有用途之间共享这些 https stackoverflow com a 3256825 176841 并且GC不会移动这些 https ghc haskell org tr
  • MD5 是否仍然足以唯一标识文件?

    考虑到 MD5 算法的破坏和安全问题等 MD5 散列文件是否仍然被认为是唯一识别该文件的足够好的方法 安全性不是我在这里最关心的问题 但唯一地标识每个文件才是 有什么想法吗 是的 MD5从安全角度来说已经被彻底攻破 但意外碰撞的概率仍然微乎
  • 对嵌套列表进行排序:从排序中排除第一项[重复]

    这个问题在这里已经有答案了 SET 我有一个csv file其中包括我的茶点的当前余额 它是逗号分隔的 但在本例中逗号 为了提高可读性而删除 NAME AMOUNT PRICE Coca Cola 8 1 25 Fanta 6 1 29 D
  • 嵌套集模型,对类别中的项目进行计数

    我有一个适用于我的网站的嵌套集模型 其中包含子类别等中的项目 除了一个我无法解决的问题之外 它运行得很好 item id item name 1 Laptop 2 iPod Classic 80GB 3 iPod Classic 160GB
  • Safari 不尊重 `transform-origin` SVG 属性

    我正在尝试使用构建 SVGtransform属性 但是 虽然我的 SVG 在 Chrome 和 Firefox 中看起来符合预期 但在 Safari 中看起来却损坏了 看来 Safari 不尊重transform origin属性并始终应用
  • Oracle ODP.Net 和连接池

    我想这确实是两个问题合二为一 我们开发了一个访问 Oracle 数据库的 Net 应用程序 并注意到在更改用户的 Oracle 密码后 该应用程序会在连接字符串中使用旧密码继续运行一小段时间 据推测 这与现有连接的池化方式有关 当第一次调查
  • jQuery:在子元素之前附加子元素

    我有这样的 HTML 代码 div div class foobar div div 我想在里面附加子元素div content之前div foobar元素 怎样才能做到这一点呢 在回答你的问题之前 让我先让你更清楚 更容易地了解一些事情
  • 检测列中导致 SQL 错误的单元格

    假设我们正在尝试更改 SQL 表中列的类型 例如varchar to float 使用 ALTER TABLE
  • 我的搜索没有在谷歌地图中显示其标记有什么问题?

    我创建了一个地方搜索谷歌地图 喜欢搜索学校类型等地方 我为私立和公立学校做了标记 搜索框有效 但是当我单击输入时 它不显示公立 私立学校 是这是因为我的代码 在图标上 或标记 唯一的问题是当我单击输入时 它不显示其标记
  • 将连续日期分组在一起

    我在 Excel csv 中有一个请病假的 许多 员工列表 按以下格式列出 每个病假实例都有自己的线路 我想添加另一列 结果 它记录病期的长度 例如 Mon Tues Wed 表示这三个条目中的每一个都标有 3 我是Python新手 我想知
  • 将大型减速机拆分为较小的减速机

    我有一个称为动物的特征减速器 切片减速器 我想将这些减速器分成哺乳动物 鸟类 鱼类等 这部分很简单 因为我可以简单地使用ActionReducerMap 现在假设哺乳动物的减速器状态很大 我想将其分成几个较小的减速器 即猫的家族 狗的家族等
  • 之间有区别吗?和 * 在 cron 表达式中?奇怪的例子

    我的系统中有以下 cron 表达式 0 0 0 1 1 1 你知道吗 我不知道这意味着什么 写这篇文章的人在接下来的两周里正在度假 所以我必须亲自去了解一下 文档可以找到here https docs oracle com cd E1205
  • 递归函数中的全局变量如何保持为零?

    因此 如果我有一个带有全局变量 var 的递归函数 int var void foo if var 3 return else var foo 然后我有一个调用 foo 的函数 如下所示 void bar foo return 每次 foo
  • 在模拟器上运行 iOS 应用程序,无需构建应用程序

    我想知道是否可以在模拟器上 运行 Xcode 项目 而无需先 构建源代码 当我单击 Xcode 4 0 2 中的 运行 按钮时 它首先构建 然后运行它 是否可以在不构建的情况下运行 如果可能的话 你会怎么做 Edit 这听起来可能是一个奇怪
  • AngularJS 1.2 - ngAnimate 不工作

    我刚开始在 AngularJS 1 2 中使用 ng animate 我不确定为什么我的 ng animate 不能使用某个类名 但可以使用我在示例中看到的简单淡入淡出的默认值 在此示例中 我尝试将 ng animate 类设置为 动画 h
  • numba - guvectorize 只比 jit 快一点

    我试图并行化在许多独立数据集上运行的蒙特卡罗模拟 我发现 numba 的并行 guvectorize 实现仅比 numba jit 实现快 30 40 我找到了这些 1 https stackoverflow com questions 3