为什么将同步编程用于内存操作会更好?

时间:2019-03-03 08:17:02

标签: python asynchronous python-multiprocessing synchronous in-memory

我有一个复杂的嵌套数据结构。我遍历它,并对每个可能的uniqe对元素执行一些计算。所有这些都是内存中的数学函数。我不会读取文件或进行联网。

运行需要几个小时,do_work()被调用了25,000次。我正在寻找加快速度的方法。

尽管Pool.map()对于我的列表似乎很有用,但事实证明这很困难,因为我需要将额外的参数传递给要映射的函数。

我认为使用Python multitasking库会有所帮助,但是当我使用Pool.apply_async()调用do_work()时,它实际上会花费更长的时间。

我做了一次谷歌搜索,a blogger说,“将同步用于内存中操作-当您不进行阻塞呼叫时,异步完全是浪费。” 是吗?有人可以解释为什么吗? RAM的读写操作是否相互干扰?为什么异步调用需要花费更长的时间? do_work()将计算结果写入数据库,但不会修改我的数据结构。

当然,有一种方法可以利用我的处理器内核,而不仅仅是线性地遍历列表。


我的起点,同步进行:

     main_list   = [ [ [a,b,c,[x,y,z], ... ], ... ], ... ] # list of identical structures
     helper_list = [1,2,3]
     z = 2
     for i_1 in range(0, len(main_list)):
         for i_2 in range(0, len(main_list)):
             if i_1 < i_2: # only unique combinations
                 for m in range(0, len(main_list[i_1])):
                     for h, helper in enumerate(helper_list):
                         do_work( 
                             main_list[i_1][m][0], main_list[i_2][m][0], # unique combo
                             main_list[i_1][m][1], main_list[i_1][m][2], 
                             main_list[i_1][m][3][z], main_list[i_2][m][3][h],
                             helper_list[h]
                         )

更改了变量名称,使其更具可读性。

2 个答案:

答案 0 :(得分:4)

这只是一个普遍的答案,但是对于评论来说太长了……

首先,我认为您目前最大的瓶颈是Python本身。我不知道do_work()的作用,但是如果它占用大量CPU,则可以使用GIL来完全阻止一个进程内部的有效并行化。不管您做什么,线程都会为GIL争斗,最终将使您的代码变得更慢。请记住:Python具有真正的线程,但是CPU在单个进程内共享。 我建议您查阅David M Beazley的页面:http://dabeaz.com/GIL/gilvis,他做了很多工作来可视化Python中的GIL行为。

另一方面,模块multiprocessing允许您运行多个进程并“规避” GIL的缺点,但是要获得对相同内存位置的访问而又不会产生更大的代价或权衡,将非常棘手。

第二:如果您使用沉重的嵌套循环,则应考虑使用numba并尝试将数据结构放入numpy(结构化)数组中。这可以使您轻松获得数量级的速度。对于此类事情,Python实在是太慢了,但是幸运的是,当使用适当的库时,有很多方法可以挤出很多

总而言之,我认为您运行的代码在numbanumpy结构下可以快几个数量级。

或者,您可以尝试使用Julia之类的语言(与Python非常相似的语法重写该代码,并且该社区非常有用),并快速检查其速度以探究性能极限。 。感觉到某种东西(或代码的一部分)在没有像Python这样复杂的性能关键方面的语言中可以有多快,这总是一个好主意。

答案 1 :(得分:2)

您的任务比依赖I / O操作的CPU资源更多。当您进行长时间的I / O操作(即从网络等发送/接收内容)时,异步执行才有意义。

您可以做的是将任务拆分为多个块,并利用线程和多处理功能(在不同的CPU内核上运行)。