为什么这个多线程的RawArray访问不能正常运行?

时间:2016-12-09 00:07:12

标签: python multithreading performance python-2.7 processing-efficiency

当多线程处理Python中的大型RawArray(Kubuntu 16.10上的2.7.12+)时,我的性能比我预期的要差。该数组在线程之间共享,并且每个线程在其自己的区域上工作而不用担心与其他线程的争用,因此我不需要或希望与该数组发生任何同步/锁定。

如果我用两个线程运行我的测试代码,我得到的性能是一个线程的两倍,正如预期的那样。三个线程并不是很好(执行时间约为37%,而不是预期的33-35),但改进发生了。但是四个线程根本没有任何改进(甚至性能稍差),添加更多线程也几乎没有提供。

这是一个八线程的四核CPU(i4770K),所以也许我不应该期待过去4个线程的更多性能 - 这是正确的吗?

尽管如此,3到4线程的缺乏改善使我感到困惑,预期和实际表现之间的差距(25%对37%)是如此之大,以至于似乎必定出现问题。

关于基础访问是否同步的RawArray对冲文档(例如“设置和获取元素可能是非原子的”)。是否有可能在RawArray中发生某些潜在的同步或其他低效率?还是我误解了一些基本的东西?

以下是我的测试代码获得的结果,显示执行时间与线程数的函数关系;完成了四次运行,坐标互相绘制:

Thread Performance Graph

...在该图表中,您可以清楚地看到它在3个线程上撞墙。这是我用来测试的代码;它会创建一个大数组,将其分解为numthreads片段,并将其交给线程进行一些简单的数学运算:

import math
from multiprocessing import Process
from multiprocessing.sharedctypes import RawArray
import multiprocessing
import datetime as dt

def doMath(mpa, startidx, endidx):
    for i in range(startidx, endidx):
        mpa[i] = (math.pow(2.12354, 5.1341234)*1.234845)/4.1234234 + 1.345345

mpa = RawArray('f', 200000000)

for numthreads in range(1, 9):

    threads = []
    chunkwidth = int(math.floor(float(len(mpa))/float(numthreads)))

    for tc in range(numthreads - 1):
        threads.append(Process(target=doMath, args=(mpa, tc*chunkwidth, (tc+1)*chunkwidth)))
    threads.append(Process(target=doMath, args=(mpa, (numthreads-1)*chunkwidth, len(mpa))))

    starttime = dt.datetime.now()

    for i in range(numthreads):
        threads[i].start()

    for i in range(numthreads):
        threads[i].join()

    proctime = dt.datetime.now() - starttime

    print('num threads: ' + str(numthreads) + ' time: {:.4f}'.format(proctime.total_seconds()) + ' secs')

0 个答案:

没有答案