优化多线程numpy数组函数

时间:2015-08-05 23:09:44

标签: python multithreading numpy

给定2个大型3D点阵列(我将调用第一个"源"和第二个"目标"),我需要一个可以返回索引的函数"目的地"哪些匹配"来源"最接近这个限制:我只能使用numpy ...所以没有scipy,pandas,numexpr,cython ......

要做到这一点,我写了一个函数based on the "brute force" answer to this question。我遍历源元素,从目标中找到最接近的元素并返回其索引。由于性能问题,再次因为我只能使用numpy,我尝试多线程来加速它。以下是线程和非线程函数以及它们在8核机器上的速度比较。

import timeit
import numpy as np
from numpy.core.umath_tests import inner1d
from multiprocessing.pool import ThreadPool

def threaded(sources, destinations):
    # Define worker function
    def worker(point):
        dlt = (destinations-point) # delta between destinations and given point
        d = inner1d(dlt,dlt) # get distances
        return np.argmin(d) # return closest index

    # Multithread!
    p = ThreadPool()
    return p.map(worker, sources)


def unthreaded(sources, destinations):
    results = []
    #for p in sources:
    for i in range(len(sources)):
        dlt = (destinations-sources[i]) # difference between destinations and given point
        d = inner1d(dlt,dlt) # get distances
        results.append(np.argmin(d)) # append closest index

    return results


# Setup the data
n_destinations = 10000 # 10k random destinations
n_sources = 10000      # 10k random sources
destinations= np.random.rand(n_destinations,3) * 100
sources = np.random.rand(n_sources,3) * 100

#Compare!
print 'threaded:   %s'%timeit.Timer(lambda: threaded(sources,destinations)).repeat(1,1)[0]
print 'unthreaded: %s'%timeit.Timer(lambda: unthreaded(sources,destinations)).repeat(1,1)[0]

Retults:

threaded:   0.894030461056
unthreaded: 1.97295164054

多线程看起来很有用,但我希望在我处理的真实数据集要大得多的情况下增加2倍以上。

我们将非常感谢所有提高性能的建议(在上述限制范围内)!

1 个答案:

答案 0 :(得分:1)

好的,我一直在阅读关于python的Maya文档,我得出了这些结论/猜测:

  • 他们可能在内部使用CPython(多次引用那个文档,而不是任何其他文档。)
  • 他们不喜欢线程(许多非线程安全方法)

由于上述原因,我说它最好避免使用线程。由于GIL problem,这是一个常见问题,有几种方法可以做到这一点。

  • 尝试构建工具C/C++ extension。完成后,在C / C ++中使用线程。 个人,我只会尝试SIP工作,然后继续前进。
  • 使用multiprocessing。即使你的自定义python发行版没有包含它,你也可以使用一个工作版本,因为它是纯粹的python代码。 multiprocessing不会受到GIL的影响,因为它会产生单独的进程。
  • 以上应该为您解决。如果没有,请尝试另一个parallel tool(经过一些严肃的祈祷)。

另外,如果你正在使用外部模块,请注意尝试匹配maya的版本。这可能是因为您无法构建scipy的原因。当然,scipy拥有庞大的代码库,而Windows平台的构建能力并不是最有弹性的。