1

我有一个功能:

1) 将 hdf5 数据集作为整数 ascii 码读入

2) 将 ascii 整数转换为字符...chr() 函数

3) 将字符连接成单个字符串函数

在进行分析时,我发现绝大多数计算都花在了第 2 步上,即将 ascii 整数转换为字符。我通过使用以下方法对这个调用进行了一些优化:

''.join([chr(x) for x in file[dataSetName].value])

由于我的解析函数似乎受 cpu 限制(整数到字符的转换)而不是 i/o 限制,我希望通过专用于解析的内核数量获得或多/少的线性速度增强。连续解析一个文件需要约 15 秒...解析 10 个文件(在我的 12 核机器上)需要约 150 秒,同时使用 10 个线程。也就是说,似乎根本没有增强。

我使用以下代码来启动我的线程:

    threads=[]
    timer=[]
    threadNumber=10
    for i,d in enumerate(sortedDirSet):
        timer.append(time.time())
     #   self.loadFile(d,i)
        threads.append(Thread(target=self.loadFileargs=(d,i)))
        threads[-1].start()
        if(i%threadNumber==0):
            for i2,t in enumerate(threads):
                t.join()
                print(time.time()-timer[i2])
            timer=[]
            threads=[]

    for t in threads:
        t.join()

任何帮助将不胜感激。

4

2 回答 2

4

multiprocessing除非您生成子进程(例如),否则 Python 不能使用多个内核(由于 GIL )。因此,您不会通过为 CPU 绑定任务生成线程而获得任何性能提升。


下面是一个使用multiprocessingand的脚本示例queue

from Queue import Empty # <-- only needed to catch Exception
from multiprocessing import Process, Queue, cpu_count

def loadFile(d, i, queue):
    # some other stuff
    queue.put(result)

if name == "main":
    queue = Queue()
    no = cpu_count()
    processes = []

    for i,d in enumerate(sortedDirSet):
        p = Process(target=self.loadFile, args=(d, i, queue))
        p.start()
        processes.append(p)

        if i % no == 0:
            for p in processes:
                p.join()
            processes = []

    for p in processes:
        p.join()

    results = []
    while True:
        try:
            # False means "don't wait when Empty, throw an exception instead"
            data = queue.get(False)
            results.append(data)
        except Empty:
            break

    # You have all the data, do something with it

另一种(更复杂的)方法是使用pipe而不是queue.

生成进程,然后创建作业队列并将它们(通过pipe)发送到子进程(因此您不必每次都创建进程)也会更有效。但这会更复杂,所以让我们这样吧。

于 2013-04-30T14:35:09.437 回答
0

Freakish 的回答是正确的,这将是 GIL 阻碍你的努力。

如果你要使用 python 3,你可以使用concurrent.futures很好地做到这一点。我相信 PyPy 也向后移植了这个特性。

此外,您可以通过替换列表理解来加快代码速度:

''.join([chr(x) for x in file[dataSetName].value])

用地图:

''.join(map(chr, file[dataSetName].value))

我使用上述代码的测试(在大量随机列表上)显示使用列表理解为 15.73 秒,使用map.

于 2013-04-30T14:56:38.693 回答