Python 线程并没有提高速度

2023-12-13

为了加速某个列表处理逻辑,我编写了一个装饰器,它会 1) 拦截传入的函数调用 2) 获取其输入列表,将其分成多个部分 4) 将这些部分传递给单独线程上的原始函数 5) 组合输出和返回

我认为这是一个非常巧妙的想法,直到我对其进行编码并发现速度没有变化!尽管我看到 htop 上有多个核心忙碌,但多线程版本实际上比单线程版本慢。

这与臭名昭著的 cpython GIL 有关吗?

Thanks!

from threading import Thread 
import numpy as np 
import time

# breaks a list into n list of lists
def split(a, n):
    k, m = len(a) / n, len(a) % n
    return (a[i * k + min(i, m):(i + 1) * k + min(i + 1, m)] for i in xrange(n))

THREAD_NUM = 8 

def parallel_compute(fn):
    class Worker(Thread):
        def __init__(self, *args):
            Thread.__init__(self)
            self.result = None
            self.args = args
        def run(self):
            self.result = fn(*self.args)
    def new_compute(*args, **kwargs):        
        threads = [Worker(args[0], args[1], args[2], x) for x in split(args[3], THREAD_NUM)]
        for x in threads: x.start()
        for x in threads: x.join()
        final_res = []
        for x in threads: final_res.extend(x.result)
        return final_res        
    return new_compute

# some function that does a lot of computation
def f(x): return np.abs(np.tan(np.cos(np.sqrt(x**2))))

class Foo:
    @parallel_compute
    def compute(self, bla, blah, input_list):
        return map(f, input_list)

inp = [i for i in range(40*1000*100)]
#inp = [1,2,3,4,5,6,7]

if __name__ == "__main__": 

    o = Foo()
    start = time.time()
    res = o.compute(None, None, inp)
    end = time.time()
    print 'parallel', end - start

单线程版本

import time, fast_one, numpy as np

class SlowFoo:
    def compute(self, bla, blah, input_list):
        return map(fast_one.f, input_list)

if __name__ == "__main__": 

    o = SlowFoo()
    start = time.time()
    res = np.array(o.compute(None, None, fast_one.inp))
    end = time.time()
    print 'single', end - start

这是多处理版本"PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed".

import pathos.multiprocessing as mp
import numpy as np, dill
import time

def split(a, n):
    k, m = len(a) / n, len(a) % n
    return (a[i * k + min(i, m):(i + 1) * k + min(i + 1, m)] for i in xrange(n))

def f(x): return np.abs(np.tan(np.cos(np.sqrt(x**2))))

def compute(input_list):
    return map(f, input_list)

D = 2; pool = mp.Pool(D)
def parallel_compute(fn):
    def new_compute(*args, **kwargs):
        inp = []
        for x in split(args[0], D): inp.append(x)
        outputs_async = pool.map_async(fn, inp)
        outputs = outputs_async.get()
        outputs = [y for x in outputs for y in x]
        return outputs
    return new_compute

compute = parallel_compute(compute)

inp = [i for i in range(40*1000)]

if __name__ == "__main__": 

    start = time.time()
    res = compute(inp)
    end = time.time()
    print 'parallel', end - start
    print len(res)

是的,当你的线程正在执行用 Python 实现的 CPU 密集型工作时(不是通过 C 扩展来实现的,C 扩展可以在从 Python 结构中编组/解组数据之前和之后释放 GIL),GIL 就是一个问题。

我建议使用多处理模型、没有它的 Python 实现(IronPython、Jython 等)或完全不同的语言(如果您正在做性能敏感的工作,那么语言是没有止境的)nearly与 Python 一样流畅,但运行时性能要好得多)。

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

Python 线程并没有提高速度 的相关文章

随机推荐

  • 无法通过 Kendo UI 图表上的 xpath 定位 SVG 元素

    我确实尝试了一些 xpath 但似乎运气不佳 我想点击国家 然后点击图表 给出下面的屏幕截图 网站网址是 https demos telerik com kendo ui bar charts column 我尝试了xpath text t
  • 迭代 PriorityQueue 不会产生有序结果

    import java util class Priority public static void main String args PriorityQueue
  • python正则表达式中的匹配括号[重复]

    这个问题在这里已经有答案了 我有类似的东西 store s 结束行就像 1 家商店 我想使用Python正则表达式来匹配它 我尝试过类似的东西re match store s text 但它不起作用 这是我尝试过的代码 import re
  • Jenkins - 构建步骤之间的条件

    我想使用 Jenkins 构建一个 Maven 项目 但是 只有当 SVN 存储库中的某个文件发生更改 并且包含特殊密钥 时才必须构建项目 所以我的计划是创建一个包含两个构建步骤的作业 第一步执行一个 shell 或 python 脚本来检
  • Delphi非可视化TTree实现

    我正在寻找一种非可视持久树 TStringTree 实现 如果有人知道它的任何良好实施 请告诉我 Thanks 你会发现一个灵活的 非可视化的树结构DI 容器图书馆 商业 然而 正如其他人上面所指出的 开发自己的功能确实非常容易 只需添加您
  • /proc 的内核模块

    如何编写一个内核模块 在 proc 中创建一个名为 mymod 的目录 并在其中创建一个名为 mymodfile 的文件 该文件在写入时应接受 1 到 3 范围内的数字 并在读取时根据已写入的数字返回以下消息 1 当前系统时间 以微秒精度为
  • RenderScript 源代码在哪里

    我正在大学项目中研究 RenderScript 我们想要找到选择 RenderScript 代码运行位置的调度程序 在 CPU 上 GPU DSP 并研究它如何做出这种选择 问题是 我们找不到与调度程序相关的任何源代码 事实上 我们在源代码
  • 在 Swift 中修改字典数组

    我是 Swift 新手 在理解数组和字典的某些方面遇到了一些麻烦 我有一个字典数组 我使用了类型别名 例如 typealias myDicts Dictionary
  • 无服务器框架 v1 - 一个服务中的多个资源

    我有两个资源 游戏和玩家 都有crud功能 这些应该位于同一个无服务器服务中吗 我想将它们分开 但是如何将它们放在同一个 api 网关中 无服务器框架项目部署单个 API 网关 因此 如果您希望它位于不同的 API 网关中 您需要单独的无服
  • 获取 Internet Explorer 选项卡标题

    我正在尝试获取所有打开的 IE 选项卡标题的列表或搜索特定的选项卡标题 我一直在使用它 但由于某种原因并不适用于每个选项卡 Get a handle to an application window DllImport USER32 DLL
  • 删除数组中的重复项

    我编写了一个程序来删除数组中的重复项 但该程序的 if 条件始终保持为 true 我明白问题所在 将 arr i 更改为 arr count 并通过 malloc 分配内存 但程序按原样打印数组而不删除重复项 include
  • MFC 对话框资源可以附加到 CChildView 吗?

    我有一个单文档 MFC 应用程序 其中包含MainFrame 源自 CFrameWnd 并包含在其中CChildView 派生形式CWnd 这些是由 VS MFC 向导生成的 在资源编辑器中 我设计了一个简单的 UI 并将其标记为IDD C
  • jQuery 点击事件返回 false

    我的点击事件设置如下 dialogLink click function dialog this return false 都有一个 return false 有人可以解释一下它的作用以及是否需要吗 你什么时候回来false从事件处理程序中
  • 403 Forbidden(错误代码:50001):添加角色时缺少访问权限 |不和谐.py

    我正在尝试快速为人们分配不同的角色 以便给用户留下他们的名字是 Rainbow 的印象 是的 我知道这违反了 TOS 并且我首先在删除角色之前为人们添加角色 但是 在添加角色时 我在这篇文章的标题中收到错误 我已经研究过这个问题并尝试了很多
  • 在 NumPy 数组的每个单元格高效评估函数

    给定 NumPy 数组A 最快 最有效的应用方法是什么same功能f to every cell 我分配给A i j by f A i j 功能f 没有二进制输出 因此屏蔽操作无济于事 每个单元格的双循环迭代是最佳解决方案吗 你可以只是矢量
  • Android凌空上传图片

    我跟着本教程将图像上传到我的服务器 但是 一旦我单击图库中的一张图片 它就会关闭我的应用程序 我有两个按钮 一个用于浏览 另一个用于用户做出选择后上传 要浏览我这样做 private void showFileChooser Intent
  • 对 URL 字符串中的 ID 进行加密/编码

    只是想在我的网站上做一些安全工作 并尝试找出确保 ID 安全的最佳途径 例子 http localhost page php id 90 TO http localhost share 22349234987sdsdf9sdf8742349
  • PDF 文件的 CUPS 打印

    我怎样才能告诉lpr命令 CUPS 我的文件实际上是 PDF lpr file pdf 不会打印任何东西 这真的是基于 CUPS 的吗 lpr 还是安装 CUPS 之前未删除的另一个假脱机系统的残余 通过运行来检查ldd which lpr
  • Microsoft graph API:通过 iCalUid 查找事件

    我想拒绝一次定期会议 我只有 masterSerieId iCalId 该实例的时间 你知道我如何取消该实例吗 我是否必须使用实例的 masterId 和时间进行查询才能查找事件 id 还是有一种方法可以使用 iCalId 查找 event
  • Python 线程并没有提高速度

    为了加速某个列表处理逻辑 我编写了一个装饰器 它会 1 拦截传入的函数调用 2 获取其输入列表 将其分成多个部分 4 将这些部分传递给单独线程上的原始函数 5 组合输出和返回 我认为这是一个非常巧妙的想法 直到我对其进行编码并发现速度没有变