Python多处理:检查内存是共享的还是被复制的

Python多处理:检查内存是共享的还是被复制的,python,python-multithreading,python-multiprocessing,pathos,Python,Python Multithreading,Python Multiprocessing,Pathos,我必须从sklearn KDTree中查询大量向量,这是searcher类的路径。我尝试使用python多处理并行查询它们,但是并行代码所花费的时间几乎与单个版本相同(或更多) import time, numpy as np from sklearn.neighbors import KDTree from multiprocessing import Pool def glob_query(arg, **kwarg): return Searcher.query(*arg, **k

我必须从sklearn KDTree中查询大量向量,这是searcher类的路径。我尝试使用python多处理并行查询它们,但是并行代码所花费的时间几乎与单个版本相同(或更多)

import time, numpy as np
from sklearn.neighbors import KDTree
from multiprocessing import Pool

def glob_query(arg, **kwarg):
    return Searcher.query(*arg, **kwarg)

class Searcher:
    def __init__(self, N, D):
            self.kdt = KDTree(np.random.rand(N,D), leaf_size=30, metric="euclidean")

    def query(self, X):
            return self.kdt.query(X, k=5, return_distance=False)

    def query_sin(self, X):
            return [self.query(x) for x in X]

    def query_par(self, X):
            p = Pool(4)
            return p.map(glob_query, zip([self]*len(X), X))

if __name__=="__main__":
    N = 1000000     # Number of points to be indexed
    D = 50          # Dimensions
    searcher = Searcher(N, D)

    E = 100         # Number of points to be searched
    points = np.random.rand(E, D)

    # Works fine
    start = time.time()
    searcher.query_sin(points)
    print("Time taken - %f"%(time.time()-start))

    # Slower than single core
    start = time.time()
    print searcher.query_par(points)
    print("Time taken - %f"%(time.time()-start))

Time taken - 28.591089
Time taken - 36.920716
我想知道

  • 如果我的kd树是跨每个工作线程复制的
  • 有没有其他方法可以并行搜索(使用pathos?)

池启动的进程基本上是当时父进程的副本。因为您在池之前创建kd树,所以所有子级都应该有kd树

请注意,创建新进程需要时间和内存

每次映射函数返回结果时,都会使用IPC将结果发送回父进程。根据返回的数据的大小,这可能会有很大的开销

但是在你尝试改进之前,先测量一下。如果不知道问题的原因,就无法解决问题

您可以使用探查器查看程序在何处花费时间


或者您可以使用
imap
imap\u unordered
返回结果的迭代器。在启动
imap
之前打印时间。在
query
方法中打印运行查询前后的当前时间。还打印迭代器生成结果的时间。这应该能让您了解程序大部分时间都花在哪里。

池启动的进程基本上是当时父进程的副本。因为您在池之前创建kd树,所以所有子级都应该有kd树

请注意,创建新进程需要时间和内存

每次映射函数返回结果时,都会使用IPC将结果发送回父进程。根据返回的数据的大小,这可能会有很大的开销

但是在你尝试改进之前,先测量一下。如果不知道问题的原因,就无法解决问题

您可以使用探查器查看程序在何处花费时间


或者您可以使用
imap
imap\u unordered
返回结果的迭代器。在启动
imap
之前打印时间。在
query
方法中打印运行查询前后的当前时间。还打印迭代器生成结果的时间。这会让你知道程序大部分时间都花在哪里。

你的代码看起来不错。我猜额外的时间来自于在池中创建4个进程。尝试在搜索者的init方法中创建池,看看是否确实如此

关于您的问题,当您打开一个新进程时,传递的对象将复制到新进程

如果在Windows中运行,那么启动的每个进程都会导致python在新进程中重新导入所有代码,并对变量进行pickle以复制它们(对于短期运行的进程来说,这可能会很昂贵)


在linux中,所有这一切都被os.fork所取代,您的代码看起来很好。我猜额外的时间来自于在池中创建4个进程。尝试在搜索者的init方法中创建池,看看是否确实如此

关于您的问题,当您打开一个新进程时,传递的对象将复制到新进程

如果在Windows中运行,那么启动的每个进程都会导致python在新进程中重新导入所有代码,并对变量进行pickle以复制它们(对于短期运行的进程来说,这可能会很昂贵)


在linux中,所有这些都被os.fork所取代,我是pathos的作者。如其他答案所述,
多处理
将对象复制到新进程。
pathos
的情况也是如此,因为它建立在
多处理的分支上
pathos
可以帮助您:(1)它将提供更好的序列化,(2)可以接受多个参数的更灵活的
map
,以及(3)在启动多个
池时消除一些开销
…但这听起来不像您的情况

如果单独的计算非常简单,那么
多处理.dummy
中的线程可能是更好的方法。你可以试试看,看看它是否能加快速度。界面是相同的,因此代码中几乎没有可编辑的内容。另外,正如其他人所建议的,如果您不需要维护结果的顺序,
imap\u unordered
通常是
池中
映射
函数中速度最快的


通常,最好的做法是尝试几种
地图
,看看哪种最适合你的情况。

我是
悲情
的作者。如其他答案所述,
多处理
将对象复制到新进程。
pathos
的情况也是如此,因为它建立在
多处理的分支上
pathos
可以帮助您:(1)它将提供更好的序列化,(2)可以接受多个参数的更灵活的
map
,以及(3)在启动多个
池时消除一些开销
…但这听起来不像您的情况

如果单独的计算非常简单,那么
多处理.dummy
中的线程可能是更好的方法。你可以试试看,看看它是否能加快速度。界面是相同的,因此代码中几乎没有可编辑的内容。另外,正如其他人所建议的,如果您不需要维护结果的顺序,
imap\u unordered
通常是
池中
映射
函数中速度最快的


通常最好的做法是尝试几种
map
,看看哪种最适合您的情况。

如果我在
init
中创建池,我会收到一个错误,说
pool o