python中二维数组操作的高效并行化

2024-01-12

我正在尝试使用二维数组上的并行操作joblibpython 中的库。这是我的代码

from joblib import Parallel, delayed
import multiprocessing
import numpy as np

# The code below just aggregates the base_array to form a new two dimensional array
base_array = np.ones((2**12, 2**12), dtype=np.uint8)
def compute_average(i, j):
    return np.uint8(np.mean(base_array[i*4: (i+1)*4, j*4: (j+1)*4]))

num_cores = multiprocessing.cpu_count()
new_array = np.array(Parallel(n_jobs=num_cores)(delayed(compute_average)(i, j) 
                                        for i in xrange(0,1024) for j in xrange(0,1024)), dtype=np.uint8)

上面的代码比下面的基本嵌套 for 循环花费更多的时间。

new_array_nested = np.ones((2**10, 2**10), dtype=np.uint8)
for i in xrange(0,1024):
    for j in xrange(0,1024):
         new_array_nested[i,j] = compute_average(i,j)

为什么并行操作需要更多时间?如何提高上面代码的效率呢?


Wow! Absolutely loved your code. It worked like a charm improving the total efficiency by 400x. I'll try to read more about numba and jit compilers, but can you write briefly of why it is so efficient. Thanks once again for all the help! – Ram https://stackoverflow.com/users/4522548/ram Jan 3 '18 at 20:30

We can quite easily get somewhere under 77 [ms], but it takes mastering a few steps to get there, so let's start:


问:为什么并行操作需要更多时间?

因为建议的步骤是joblib创建许多完整的进程副本 - 以便摆脱 GIL 步进pure-[SERIAL] https://stackoverflow.com/revisions/8337936/5跳舞(一个接一个)但是(!)这包括所有内存传输的附加成本(对于确实很大的内存传输非常昂贵/敏感)numpy数组)的所有变量和整个Python解释器及其内部状态,在它开始对你的“有效负载”计算策略进行“有用”工作的第一步之前,
so
所有这些实例化开销的总和很容易变得比与开销无关的反比例期望更大1 / N factor,
你设置的地方N ~ num_cores.

For details,阅读阿姆达尔定律重新公式化尾部的数学公式here. https://stackoverflow.com/revisions/18374629/3


Q:上面的代码可以帮助提高效率吗?

尽可能节省所有管理费用:
- 在可能的情况:
- 在进程生成端,尝试使用n_jobs = ( num_cores - 1 )为“主要”流程的推进和性能提升时的基准测试留出更多空间
- 在进程终止端,避免从返回值中收集和构造一个新的(可能尺寸很大)对象,而是预先分配一个足够大的进程本地数据结构,并返回一些高效的序列化对象,以便轻松且无阻塞地合并每个部分返回结果的对齐方式。

这两种“隐藏”成本都是您的主要设计敌人,因为它们会线性添加到纯成本中。[SERIAL]整个问题解决方案的计算路径的一部分(ref.:这两者的影响在严格开销阿姆达尔定律公式 https://stackoverflow.com/revisions/18374629/3 )


实验和结果:

>>> from zmq import Stopwatch; aClk = Stopwatch()
>>> base_array = np.ones( (2**12, 2**12), dtype = np.uint8 )
>>> base_array.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA      : True
  WRITEABLE    : True
  ALIGNED      : True
  UPDATEIFCOPY : False
>>> def compute_average_per_TILE(               TILE_i,   TILE_j ): // NAIVE MODE
...     return np.uint8( np.mean( base_array[ 4*TILE_i:4*(TILE_i+1),
...                                           4*TILE_j:4*(TILE_j+1)
...                                           ]
...                               )
...                      )
... 
>>> aClk.start(); _ = compute_average_per_TILE( 12,13 ); aClk.stop()
25110
  102
  109
   93

这大约需要93 [us]每一次射击。怀有大约的期望1024*1024*93 ~ 97,517,568 [us]覆盖整个均值处理base_array.

通过实验,我们可以很好地看到管理不善的开销的影响,天真的嵌套实验采取了:

>>> aClk.start(); _ = [ compute_average_per_TILE( i, j )
                                              for i    in xrange(1024)
                                              for    j in xrange(1024)
                        ]; aClk.stop()
26310594
^^...... 
26310594 / 1024. / 1024. == 25.09 [us/cell]

大约减少 3.7 倍(由于未产生“尾部”部分(单个返回值的分配)开销 2**20 次,但仅在终端分配时一次。

然而,更多惊喜还在后面。


这里什么是合适的工具?

从来没有一个放之四海而皆准的规则,也没有放之四海而皆准的规则。

Given
每次调用的进程不会超过 4x4 矩阵图块(实际上少于25 [us]根据提议的joblib- 精心策划的衍生2**20呼叫,分布在〜.cpu_count()按照原始提案完全实例化流程

...( joblib.Parallel( n_jobs = num_cores )( 
     joblib.delayed( compute_average )( i, j ) 
                                    for i    in xrange( 1024 )
                                    for    j in xrange( 1024 )
     )

性能确实还有提升的空间。

对于这些小规模矩阵(从这个意义上来说,并非所有问题都那么令人满意),人们可以期望从更智能的内存访问模式和减少源自 Python GIL 的弱点中获得最佳结果。

由于每次调用的跨度只是 4x4 的微型计算,因此更好的方法是利用智能矢量化(所有数据都适合缓存,因此缓存内计算是寻找最佳性能的假期之旅)

最好的(仍然是非常天真的矢量化代码)
能够从~ 25 [us/cell] to 少于~ 74 [ns/cell](仍然有空间进行更好的对齐处理,因为它需要~ 4.6 [ns] / a base_array细胞处理),因此,如果缓存内优化的矢量化代码能够正确制作,那么预计会得到另一个级别的加速。

In 77 [ms]?!值得这样做,不是吗?

不是97秒,
不是25秒,
但小于77 [ms]只需敲击几下键盘,如果更好地优化呼叫签名,可能会敲出更多:

>>> import numba
>>> @numba.jit( nogil = True, nopython = True )
... def jit_avg2( base_IN, ret_OUT ):  // all pre-allocated memory for these data-structures
...     for i in np.arange( 1024 ):    // vectorised-code ready numpy iterator
...         for j in np.arange( 1024 ):// vectorised-code ready numpy iterator 
...             ret_OUT[i,j] = np.uint8( np.mean( base_IN[4*i:4*(i+1),
...                                                       4*j:4*(j+1)
...                                                       ]
...                                               )
...                                      )
...     return                         // avoid terminal assignment costs
... 

>>> aClk.start(); _ = jit_avg2( base_array, mean_array ); aClk.stop()
1586182 (even with all the jit-compilation circus, it was FASTER than GIL-stepped nested fors ...)
  76935
  77337
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python中二维数组操作的高效并行化 的相关文章

  • 通过pip安装lxml时出错:需要Microsoft Visual C++ 14.0

    我使用的是 Windows 10 机器 最近从 python 2 7 迁移到 3 5 当尝试通过 pip 安装 lxml 时 它会停止并抛出此错误消息 构建 lxml etree 扩展错误 需要 Microsoft Visual C 14
  • pandas 使用查询功能检查列是否为空

    我有 pandas 数据框 我想在它的查询函数上执行 isnull 或 not isnull 条件 如下所示 In 67 df data pd DataFrame a 1 20 None 40 50 In 68 df data Out 68
  • pandas 用 nan 值切割了一系列

    我想将 pandas cut 函数应用于包含 NaN 的序列 期望的行为是它对非 NaN 元素进行存储并为 NaN 元素返回 NaN import pandas as pd numbers with nan pd Series 3 1 2
  • Excel函数:引用单元格中的数组

    我在单元格 A1 中有一个数组 通过 A1 G6 J6 aa b ccc 1 现在我想将单元格 A1 用于 B1 中的数组公式 基本上B1应该是 B1 SUMPRODUKT C6 C12 B6 B12 G6 J6 但我不想直接引用 G6 J
  • 在 Kivy 应用程序中获取文本输入值

    Python Kivy 新手尝试构建一个测试应用程序 其中包含输入框 确定按钮和单击确定按钮时应更改文本的标签 但我得到了 NameError 全局名称 txt1 未定义 我究竟做错了什么 import Kivy import kivy i
  • Keras AttributeError:“顺序”对象没有属性“predict_classes”

    我试图按照本指南找到模型性能指标 F1 分数 准确性 召回率 https machinelearningmastery com how to calculate precision recall f1 and more for deep l
  • 使用数据库数据模型生成 SQLAlchemy 模型、架构和 JSON 响应

    将 Flask 和 SQLAlchemy 用于 Python Web 应用程序 我的目标是创建一个系统 在其中我可以 从现有 PostgreSQL 数据库导入数据模型 并将它们映射到相应 SQLAlchemy 模型中的字段 使用这些 SQL
  • Pytorch“展开”等价于 Tensorflow [重复]

    这个问题在这里已经有答案了 假设我有大小为 50 50 的灰度图像 在本例中批量大小为 2 并且我使用 Pytorch Unfold 函数 如下所示 import numpy as np from torch import nn from
  • 读取 JSON 文件并将其漂亮打印到另一个文件

    我有一个复杂 嵌套 的 json 文本文件 它是文本文件中的一长行 有什么方法可以读取文件 在 python 中 并将 json 缩进 漂亮地打印到新的文本文件中吗 使用读取文件json load 并使用json dump 在指定缩进值时将
  • 在 matplotlib 中查看然后自动关闭图形?

    我必须检查我的参数设置是否正确 因此我需要绘制许多图 为了绘制这些图 我选择使用 matplotlib 每次检查后 我需要单击左上角的关闭按钮 这很微不足道 那么有没有什么方法可以让剧情在3 5秒左右显示并且无需点击就自动关闭呢 我知道关于
  • 向 list.extend() 传递不可迭代对象

    我正在创建一个公共方法来允许调用者将值写入设备 例如将其称为 write vals 由于这些值将实时输入 因此我希望通过允许用户输入列表或单个值来简化用户的生活 具体取决于他们需要写入的值的数量 例如 write to device 1 2
  • 无法写入文本文件

    我正在运行一些测试并需要写入文件 当我运行测试时open file r 不写入文件 测试脚本如下 class GetDetailsIP TestGet def runTest self self category PTZ try This
  • 在pycharm中使用多处理时如何调试

    我正在 pycharm 社区版中使用 anaconda2 调试多进程程序 它有几个后台工作进程 工作进程将检查输入队列以检索任务 而不会休眠 直到收到任务 事实上 我只对主要流程感兴趣 但是pycharm调试器总是单步进入子进程 看起来主进
  • Pytest 插件:覆盖 pytest_runtest_call 和朋友

    我正在为我的一个项目使用 pytest 开发一个测试套件 由于项目的性质 我需要创建一个 Pytest 插件来控制测试的运行方式 它们不是在本地运行 而是发送到不同的进程来运行 我知道关于xdist但我认为这并不能解决我的问题 我一直在通过
  • 返回 OSError 异常类的子类实例的逻辑在哪里?

    我一直在寻找一些对某些人来说可能相对愚蠢的东西 但对我来说非常有趣 输入和输出错误已合并为OSError在 Python 3 3 中 异常类层次结构发生了变化 关于内置类的一个有趣的特性OSError是这样 它在传递时返回它的子类errno
  • 是否可以使用 Google BERT 来计算两个文本文档之间的相似度?

    是否可以使用 Google BERT 来计算两个文本文档之间的相似度 据我了解 BERT 的输入应该是有限大小的句子 一些作品使用 BERT 来计算句子的相似度 例如 https github com AndriyMulyar semant
  • 如何按分层类别结构中的值对 pandas 中的数据框进行排序

    我有一个 pandas 数据框 pd DataFrame category Transport Transport Car Transport Train Household Household Utilities Household Ut
  • 使用 PyODBC 选择表中的列名

    我正在编写一个 Python 程序 该程序使用 PyODBC 从 Microsoft Access mdb 文件中选择一些数据 我需要发现几个不同表的列名 在 SQL Server 中 这可以通过使用类似的查询来完成 SELECT c na
  • 将键上的对象数组和总和值减少到数组中

    我有以下对象 data name foo type fizz val 9 name foo type buzz val 3 name bar type fizz val 4 name bar type buzz val 7 并使用 loda
  • Django migrate:不创建表

    经过一些错误后 我删除了数据库 删除了所有迁移文件 我留下了init py 现在 当我跑步时 python migrate py makemigrations It creates migrations correctly python m

随机推荐

  • Django 2.0 allauth Facebook 2018

    我使用 Django all auth 登录 Twitter 和 Google 现在 Facebook 出现问题 尝试了 localhost 127 0 0 1 etc 之间的每一个组合 也通过将我的主机更改为 local domain c
  • 将记录添加到 Firebase 数据库时发送电子邮件

    我想向签名用户发送一封电子邮件 其中包含用户添加到 Firebase 数据库的数据 我正在使用 AngularJS 用户界面 是否有 Firebase 模块会触发电子邮件 并将数据添加到签名用户中 谢谢 拉杰什 你应该调查一下Firebas
  • 为什么 Python 代码在函数中运行得更快?

    def main for i in xrange 10 8 pass main 这段代码在Python中运行 注 计时是用Linux中BASH中的time函数完成的 real 0m1 841s user 0m1 828s sys 0m0 0
  • CORS 策略已阻止从 '' from origin '' 获取数据:请求的资源上不存在 'Access-Control-Allow-Origin' 标头

    I have this api method get that is connected to a lambda function that does a simple select from a database if i test th
  • Android:从正在运行的服务获取变量

    我的活动启动了一个服务 当我关闭我的应用程序时 该服务将继续运行 好吧 没错 但是 当我在活动中再次打开应用程序时 我需要知道在我之前启动的正在运行的服务 类 上定义的公共变量的值 我怎样才能做到这一点 Thanks 如果您将 Activi
  • iOS 5 Segue 实现

    在两个视图控制器之间实现 segue 时 如何使用 segue 对象更改目标视图控制器的属性 文档说这可以在prepareForSegue sender 方法中完成 我尝试过但没有成功 我不知道你是否还需要这个答案 但这是一个如此孤独的帖子
  • Rails3 rspec 问题

    我正在尝试rails3 我在用铁路教程 http railstutorial org 探索有关 Rails3 的更多信息的网站 该教程非常适合入门 我对rails2 的经验很少 我的 rspec 存在问题 目前阻碍了我的进度 我看到教程推荐
  • 获取 chrome 下载文件夹

    Windows 7 中的默认下载文件夹是c 用户 用户名 下载对于 Chrome 但可以通过设置将默认下载文件夹设置为其他文件夹 我需要找出哪个文件夹是下载文件夹 所以如果我将下载文件夹设置为c dd 那么我需要找出具体的文件夹 有没有办法
  • 如何在 chrome 中检查系统时间格式 - 在 JavaScript 中是 12 小时还是 24 小时?

    date toLocaleTimeString不适用于 Chrome 并且始终以 12 小时格式返回时间 我需要根据系统的时间格式显示时间 简短的回答是No您无法在浏览器中获取默认时间格式 因为它依赖于系统和浏览器设置 而 JavaScri
  • 如何将 CoreML 模型转换为 TensorFlow 模型?

    我了解到可以将 TensorFlow 模型 pb 文件转换为 CoreML mlmodel 以在 iOS 平台上运行 但我有一些想要在张量流上运行的 mlmodel 文件 所以我想知道是否有任何方法可以将它们转换为 pb 文件或任何其他方式
  • LINQ to Entities 用于减去 2 个日期

    我正在尝试使用 LINQ 和实体框架确定两个日期之间的天数 它告诉我它无法识别 System TimeSpan 类上的 Subtract 这是 LINQ 查询的 where 部分 where DateTime Now Subtract vi
  • 比 windows.h 的 Beep() 更快的替代方案

    我正在做一个个人项目 我想用旧的业余无线电无线电传输一些数据 我的第一份申请草案是这样的 我用 4 个 信号 构造一个字节 5000hz表示 00 6khz 表示 01 7khz的意思是 10 8khz的意思是 11 9khz 意思和上一个
  • 如何禁用 NetBeans 8.1 中烦人的警告/提示

    我正在 NetBeans 中使用 Java 和 Jersey 我的所有端点都标有以下提示 将方法转换为异步 这个提示确实污染了我通常寻找代码更改 错误的右侧排水沟 首选项 gt 编辑器 gt 提示中没有任何内容似乎会影响此提示 Cheers
  • Git 与 --squash 合并,同时保留每次提交的日志

    初始场景 A master B C D development 合并后我想要什么 squash A E master development B C D 在树枝上master git log将会 commit E Squashed comm
  • php:编写 .ics (iCal) 文件?日期格式?

    我不是一个 php 专家 在格式化 ics 文件的日期时遇到了麻烦 所以我有一个循环为每个生成一个日历条目 post 在我的例子中 post 是一个事件 foreach posts as post setup postdata post i
  • 从 Windows 的 git bash 激活 pyenv

    我在 Windows 7 64 位 上使用 gitbash 我尝试使用 python 3 4 的内置 venv 模块创建一个 venv 方法是调用python m venv venv 并且创建成功 但是生成的 venv 不包含 bash a
  • AVPlayerLayer 不显示 AVPlayer 视频?

    让 AVPlayer 视频内容显示在自己的视图中的技巧是什么 我们正在使用以下 AVPlayer 代码 但屏幕上没有出现任何内容 我们知道视频在那里 因为我们能够使用 MPMoviePlayerController 来显示它 这是我们正在使
  • 如何通过C#代码在文本框中向下滚动

    我正在使用 winforms 并且偶尔更新一个文本框 显示消息 但是 当文本到达框的末尾时 它会产生滚动条 我不知道如何向下滚动到底部 我唯一看到的是 ScrollToCaret 但插入符位于文本的开头 滚动的命令是什么 您可以通过使用名为
  • 将 ASP.NET 4 Web 应用程序部署到 IIS6 服务器后,工作进程回收导致其大部分时间停止工作

    这是一个非常奇怪的情况 所以希望我能很好地解释它 我正在将 ASP NET 4 Webforms 应用程序部署到运行 IIS6 的 Windows Server 2003 SP2 服务器 问题是 当应用程序池回收其工作进程 w3wp exe
  • python中二维数组操作的高效并行化

    我正在尝试使用二维数组上的并行操作joblibpython 中的库 这是我的代码 from joblib import Parallel delayed import multiprocessing import numpy as np T