Cython prange 对于 4 个线程来说比范围要慢

2023-11-23

我目前正在尝试遵循一个简单的示例,使用 cython 的 prange 并行化循环。 我已经安装了允许 openmp 的 OpenBlas 0.2.14,并针对 openblas 从源代码编译了 numpy 1.10.1 和 scipy 0.16。为了测试库的性能,我遵循以下示例:http://nealhughes.net/parallelcomp2/。 要计时的功能是从站点复制的:

import numpy as np
from math import exp 
from libc.math cimport exp as c_exp
from cython.parallel import prange,parallel

def array_f(X):

    Y = np.zeros(X.shape)
    index = X > 0.5
    Y[index] = np.exp(X[index])

    return Y

def c_array_f(double[:] X):

    cdef int N = X.shape[0]
    cdef double[:] Y = np.zeros(N)
    cdef int i

    for i in range(N):
        if X[i] > 0.5:
            Y[i] = c_exp(X[i])
        else:
            Y[i] = 0

    return Y


def c_array_f_multi(double[:] X):

    cdef int N = X.shape[0]
    cdef double[:] Y = np.zeros(N)
    cdef int i
    with nogil, parallel():
        for i in prange(N):
            if X[i] > 0.5:
                Y[i] = c_exp(X[i])
            else:
                Y[i] = 0

    return Y

代码作者报告了 4 个核心的以下加速情况:

from thread_demo import *
import numpy as np
X = -1 + 2*np.random.rand(10000000) 
%timeit array_f(X)
1 loops, best of 3: 222 ms per loop
%timeit c_array_f(X)
10 loops, best of 3: 87.5 ms per loop 
%timeit c_array_f_multi(X)
10 loops, best of 3: 22.4 ms per loop

当我在我的机器(带有 osx 10.10 的 macbook pro )上运行这些示例时,我得到以下导出时间OMP_NUM_THREADS=1

In [1]: from bla import *
In [2]: import numpy as np
In [3]: X = -1 + 2*np.random.rand(10000000)
In [4]: %timeit c_array_f(X)
10 loops, best of 3: 89.7 ms per loop
In [5]: %timeit c_array_f_multi(X)
1 loops, best of 3: 343 ms per loop

and for OMP_NUM_THREADS=4

In [1]: from bla import *
In [2]: import numpy as np
In [3]: X = -1 + 2*np.random.rand(10000000)
In [4]: %timeit c_array_f(X)
10 loops, best of 3: 89.5 ms per loop
In [5]: %timeit c_array_f_multi(X)
10 loops, best of 3: 119 ms per loop

我在 openSuse 机器上看到了同样的行为,因此我提出了问题。作者如何获得 4 倍的速度提升,而相同的代码在我的 2 个系统上的 4 个线程上运行速度较慢。

用于生成的设置脚本*.c & .so也与博客中使用的相同。

from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy as np

ext_modules=[
    Extension("bla",
              ["bla.pyx"],
              libraries=["m"],
              extra_compile_args = ["-O3", "-ffast-math","-march=native", "-fopenmp" ],
              extra_link_args=['-fopenmp'],
              include_dirs = [np.get_include()]
              ) 
]

setup( 
  name = "bla",
  cmdclass = {"build_ext": build_ext},
  ext_modules = ext_modules
)

如果有人能向我解释为什么会发生这种情况,那就太好了。


1)的一个重要特点是prange(像任何其他parallel for循环)的特点是它激活了乱序执行,这意味着循环可以按任意顺序执行。当迭代之间不存在数据依赖性时,乱序执行确实会带来回报。

我不知道 Cython 的内部结构,但我认为如果boundschecking 没有关闭,循环不能任意执行,因为下一次迭代将取决于当前迭代中数组是否越界,因此问题几乎变得串行,因为线程必须等待结果。这是您的代码的问题之一。事实上 Cython 确实给了我以下警告:

warning: bla.pyx:42:16: Use boundscheck(False) for faster access

所以添加以下内容

from cython import boundscheck, wraparound

@boundscheck(False)
@wraparound(False)
def c_array_f(double[:] X):
   # Rest of your code

@boundscheck(False)
@wraparound(False)
def c_array_f_multi(double[:] X):
   # Rest of your code

现在让我们用您的数据对它们进行计时X = -1 + 2*np.random.rand(10000000).

进行边界检查:

In [2]:%timeit array_f(X)
10 loops, best of 3: 189 ms per loop
In [4]:%timeit c_array_f(X)
10 loops, best of 3: 93.6 ms per loop
In [5]:%timeit c_array_f_multi(X)
10 loops, best of 3: 103 ms per loop

无边界检查:

In [9]:%timeit c_array_f(X)
10 loops, best of 3: 84.2 ms per loop
In [10]:%timeit c_array_f_multi(X)
10 loops, best of 3: 42.3 ms per loop

这些结果与num_threads=4(我有 4 个逻辑核心)并且加速约为 2 倍。在进一步讨论之前我们还可以再剃掉一些ms通过声明我们的数组是连续的,即声明X and Y with double[::1].

连续数组:

In [14]:%timeit c_array_f(X)
10 loops, best of 3: 81.8 ms per loop
In [15]:%timeit c_array_f_multi(X)
10 loops, best of 3: 39.3 ms per loop

2)更重要的是工作调度这就是你的基准测试所面临的问题。默认情况下,块大小是在编译时确定的,即schedule=static然而,两台机器(您的机器和博客文章中的机器)的环境变量(例如 OMP_SCHEDULE)和工作负载很可能不同,并且它们在运行时动态地、引导性地安排作业等等。让我们尝试一下替换你的prange to

for i in prange(N, schedule='static'):
    # static scheduling... 
for i in prange(N, schedule='dynamic'):
    # dynamic scheduling... 

现在让我们对它们进行计时(仅多线程代码):

调度效果:

In [23]:%timeit c_array_f_multi(X) # static
10 loops, best of 3: 39.5 ms per loop
In [28]:%timeit c_array_f_multi(X) # dynamic
1 loops, best of 3: 319 ms per loop

You might能够根据您自己计算机上的工作负载来复制此内容。作为旁注,由于您只是想在微基准测试中测量并行代码与串行代码的性能,而不是实际代码,所以我建议您摆脱if-else条件即仅保留Y[i] = c_exp(X[i])在 for 循环内。这是因为if-else语句还会对并行代码中的分支预测和乱序执行产生不利影响。在我的机器上,通过这一更改,我的速度比串行代码提高了近 2.7 倍。

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

Cython prange 对于 4 个线程来说比范围要慢 的相关文章

  • 类的 IPython 表示

    我正在使用我创建的模块尝试 IPython 但它没有显示类对象的实际表示 相反 它显示类似的内容 TheClass module TheClass name I heavily在这个模块中使用元类 我有真正有意义的类表示 应该向用户显示 是
  • Django Rest Framework 是否有第三方应用程序来自动生成 swagger.yaml 文件?

    我有大量的 API 端点编写在django rest framework并且不断增加和更新 如何创建和维护最新的 API 文档 我当前的版本是 Create swagger yaml文件并以某种方式在每次端点更改时自动生成 然后使用此文件作
  • 如何从Python中的函数返回多个值? [复制]

    这个问题在这里已经有答案了 如何从Python中的函数返回多个变量 您可以用逗号分隔要返回的值 def get name you code return first name last name 逗号表示它是一个元组 因此您可以用括号将值括
  • 为什么 web2py 在启动时崩溃?

    我正在尝试让 web2py 在 Ubuntu 机器上运行 所有文档似乎都表明要在 nix 系统上运行它 您需要下载源代码并执行以下操作 蟒蛇 web2py py 我抓住了source http www web2py com examples
  • PyQt 使用 ctrl+Enter 触发按钮

    我正在尝试在我的应用程序中触发 确定 按钮 我当前尝试的代码是这样的 self okPushButton setShortcut ctrl Enter 然而 它不起作用 这是有道理的 我尝试查找一些按键序列here http ftp ics
  • Pycharm 在 os.path 连接上出现“未解析的引用”

    将pycharm升级到2018 1 并将python升级到3 6 5后 pycharm报告 未解析的引用 join 最新版本的 pycharm 不会显示以下行的任何警告 from os path import join expanduser
  • GUI(输入和输出矩阵)?

    我需要创建一个 GUI 将数据输入到矩阵或表格中并读取此表单数据 完美的解决方案是限制输入表单仅允许float 例如 A 1 02 0 25 0 30 0 515 0 41 1 13 0 15 1 555 0 25 0 14 1 21 2
  • 打印包含字符串和其他 2 个变量的变量

    var a 8 var b 3 var c hello my name is var a and var b bye print var c 当我运行程序时 var c 会像这样打印出来 hello my name is 8 and 3 b
  • 如何将特定范围内的标量添加到 numpy 数组?

    有没有一种更简单 更节省内存的方法可以单独在 numpy 中执行以下操作 import numpy as np ar np array a l r ar c a a 0 l ar tolist a r 它可能看起来很原始 但它涉及获取给定数
  • Python 3:将字符串转换为变量[重复]

    这个问题在这里已经有答案了 我正在从 txt 文件读取文本 并且需要使用我读取的数据之一作为类实例的变量 class Sports def init self players 0 location name self players pla
  • 使用 python/numpy 重塑数组

    我想重塑以下数组 gt gt gt test array 11 12 13 14 21 22 23 24 31 32 33 34 41 42 43 44 为了得到 gt gt gt test2 array 11 12 21 22 13 14
  • 使用 Python Oauthlib 通过服务帐户验证 Google API

    我不想使用适用于 Python 的 Google API 客户端库 但仍想使用 Python 访问 Google APIOauthlib https github com idan oauthlib 创建服务帐户后谷歌开发者控制台 http
  • 导入错误:没有名为flask.ext.login的模块

    我的flask login 模块有问题 我已经成功安装了flask login模块 另外 从命令提示符我可以轻松运行此脚本 不会出现错误 Python 2 7 r27 82525 Jul 4 2010 07 43 08 MSC v 1500
  • Python GTK+ 画布

    我目前正在通过 PyGobject 学习 GTK 需要画布之类的东西 我已经搜索了文档 发现两个小部件似乎可以完成这项工作 GtkDrawingArea 和 GtkLayout 我需要一些基本函数 如 fillrect 或 drawline
  • Spider 必须返回 Request、BaseItem、dict 或 None,已“设置”

    我正在尝试从以下位置下载所有产品的图像 我的蜘蛛看起来像 from shopclues items import ImgData import scrapy class multipleImages scrapy Spider name m
  • Python:Goslate 翻译请求返回“503:服务不可用”[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我们不允许提出寻求书籍 工具 软件库等推荐的问题 您可以编辑问题 以便用事实和引文来回答 这个问题似乎不是关于主要由程序员使用的特定编程问
  • 如果 PyPy 快 6.3 倍,为什么我不应该使用 PyPy 而不是 CPython?

    我已经听到很多关于PyPy http en wikipedia org wiki PyPy项目 他们声称它比现有技术快 6 3 倍CPython http en wikipedia org wiki CPython口译员开启他们的网站 ht
  • Firebase Firestore:获取文档的生成 ID (Python)

    我可以创建一个新文档 带有自动生成的 ID 并存储对其的引用 如下所示 my data key value doc ref db collection u campaigns add my data 我可以像这样访问数据本身 print d
  • pytest找不到模块[重复]

    这个问题在这里已经有答案了 我正在关注pytest 良好实践 https docs pytest org en latest explanation goodpractices html test discovery或者至少我认为我是 但是
  • 如何将Python3设置为Mac上的默认Python版本?

    有没有办法将 Python 3 8 3 设置为 macOS Catalina 版本 10 15 2 上的默认 Python 版本 我已经完成的步骤 看看它安装在哪里 ls l usr local bin python 我得到的输出是这样的

随机推荐

  • 内核模块中的 EXPORT_SYMBOL | insmod 期间未定义的符号

    我有一个来自 a ko 内核模块 的导出函数 foo 和 foo1 foo1 接受输入参数 一个函数指针 我从 b ko 调用 foo1 并将 foo 作为输入参数传递 我看到 b ko 未知符号 foo 的 insmod 失败 即使 a
  • Java 11 HttpClient - HttpClient 与并发 HttpRequest 的最佳比率是多少

    在下面的示例中 我创建一个 Java 11 httpClient 然后创建多个并发 HttpRequest 这是不好的做法吗 每个 HttpRequest 都应该有自己的 HttpClient 吗 HttpClient 可以拥有的 Http
  • 使用 gsub 删除第一个数字字符之前的所有字符串

    使用 gsub 删除 R 中第一个空格之前的所有字符串 在此示例中 我们尝试删除空格之前的所有内容sub 1 D name 我正在寻找非常相似的东西 但我对正则表达式不太熟悉 我想删除第一个数字字符之前的所有内容 但不删除它 例如 x lt
  • UI5控件的生命周期是如何运作的?

    有人可以更详细地解释 UI5 控件默认事件的生命周期吗 我知道有文档中的此页面它概述了控件生命周期 但是 我认为它非常简短 需要更详细的内容 有人可以列出控件事件的顺序并解释每个事件的作用吗 你是绝对正确的 控件生命周期的详细信息和实现细节
  • 如何使用 SSL/TLS 和/或消息级安全保护 RESTful php Web 服务

    我有一个用 php 编写的 RESTful Web 服务 它使用 JSON 进行通信 传输的一些数据确实很敏感 密码 我正在寻找一种方法来实现服务的合理安全级别 客户端是 silverlight 4 应用程序 我一直在寻找有关如何实施 SS
  • NodeJS 的 Web Sockets 服务器端实现

    这个问题的部分原因可能是客户端的讨论太多 让我只见树木不见森林 无论如何 这就是我想做的 我需要一个独立于平台的 WebSocket 服务器端实现 我希望它在 NodeJS 中运行 现在 我发现的有关该主题的内容 99 都与 socket
  • 如何使用照片框架快速循环浏览照片库

    我有一个应用程序 可以为我的应用程序上的每张门票创建一个独特的照片库 我需要弄清楚如何循环浏览该画廊 以便我可以一次将一张图像上传到服务器 我在 YouTube 上遵循了这些教程 Video 我目前使用 Swift 作为我的语言 我的最终目
  • 如何在 VC++ 中毒害标识符?

    功能中毒在 C 中是非常有用的技术 一般来说 它指的是使某个功能不可用 例如如果您想禁止在程序中使用动态分配 您可以 poison malloc 函数因此无法使用 中毒 标识符意味着 中毒 之后对标识符的任何引用都是硬编译器错误 例如 参见
  • Angular 6:错误类型错误:无法读取未定义的属性“toLowerCase”

    我正在以关于用户的角度六创建 CRUD 应用程序 当我尝试添加新用户时 出现以下错误 这是我收到的错误 core js 12301 ERROR TypeError Cannot read property toLowerCase of un
  • 基于 Microsoft Visual C++ Express 2010 的 64 位构建

    我正在尝试使用 Visual C Express 2010 将 VC 项目编译为 64 位 我知道 64 位编译器没有默认安装 VC Express 因此我按照此处指定的方式安装了适用于 Windows 7 的 Windows SDK ht
  • 使用 jQuery 在新窗口中打开所有外部链接

    这里是 jQuery 新手 我发现了几个网页与我想要做的事情很接近 但又不完全一样 其实我觉得以下是supposed实际工作 但它说 href http 无法识别 语法错误 有什么帮助吗 document ready function a
  • 为什么 apply 尚未绑定到 Javascript 中的函数?

    假设 为了解决这个问题 我希望能够在 Javascript 中创建一个函数 将一个数组的所有元素附加到另一个数组 如果您有权访问目标数组 实现此目的的一种方法是 var destination 1 2 3 var source 4 5 Ar
  • 为什么跳转到 case 标签会在此 switch 中交叉初始化?

    考虑以下代码 include
  • 一般来说,存储过程比现代 RDBMS 上的内联语句更有效吗? [复制]

    这个问题在这里已经有答案了 传统观点认为存储过程总是更快 所以 因为它们总是更快 所以使用它们每时每刻 我很确定这是有历史背景的 这种情况曾经发生过 现在 我并不是主张不需要存储过程 而是我想知道在现代数据库 例如 MySQL SQL Se
  • 找到图中访问所有节点的最短路径

    我有一个加权无向图G with n顶点 其中两个顶点是X and Y 我需要找到起始于的最短路径X 结束于Y并穿过 G 的所有顶点 以任何顺序 我怎样才能做到这一点 这不是旅行商问题 我不需要只访问每个顶点一次 也不想返回第一个顶点 这个问
  • F# 中的事件和委托

    我没有任何 F 经验 但有几行 C 测试代码 用于我制作的框架 需要用 F 重写 任何帮助 将不胜感激 bar Ready new Agent ReadyHandler bar Ready static void bar Ready str
  • 如何在应用程序内浏览器窗口中打开链接

    我想知道如何在应用程序内浏览器中打开链接 就像这样 你可以使用以下方法来实现flutter web browser以 Android chrome 选项卡样式在应用程序内打开网页的插件 Ex body new Center child ne
  • 从Python中的多维列表中删除前导和尾随零[关闭]

    很难说出这里问的是什么 这个问题模棱两可 含糊不清 不完整 过于宽泛或言辞激烈 无法以目前的形式合理回答 如需帮助澄清此问题以便重新打开 访问帮助中心 我有一个清单 例如 my list 1 2 2 1 0 0 1 2 1 2 0 0 1
  • 函数可以工作( boot.stepAIC ),但在另一个函数中抛出错误 - 环境问题?

    今天我在 R 代码中发现了一个奇怪的行为 我尝试了一个包 boot StepAIC 其中包含一个用于 AIC 逐步回归结果的引导函数 然而 我不认为统计背景是问题所在 我希望如此 我可以在 R 的顶层使用该函数 这是我的示例代码 requi
  • Cython prange 对于 4 个线程来说比范围要慢

    我目前正在尝试遵循一个简单的示例 使用 cython 的 prange 并行化循环 我已经安装了允许 openmp 的 OpenBlas 0 2 14 并针对 openblas 从源代码编译了 numpy 1 10 1 和 scipy 0