在多个进程之间共享只读scipy稀疏矩阵的安全性

时间:2014-12-26 17:34:49

标签: thread-safety scipy multiprocessing sparse-matrix python-multiprocessing

我有一个必须做的计算,这有点贵,我想生成多个进程来完成它。要点或多或少是这样的:

1)我有一个很大的scipy.sparse.csc_matrix(如果需要可以使用其他稀疏格式),我将从中读取(仅读取,从不写入)数据进行计算。

2)我必须做很多令人尴尬的并行计算和返回值。

所以我做了这样的事情:

import numpy as np
from multiprocessing import Process, Manager

def f(instance, big_matrix):
    """
    This is the actual thing I want to calculate. This reads lots of 
    data from big_matrix but never writes anything to it.
    """
    return stuff_calculated

def do_some_work(big_matrix, instances, outputs):
    """
    This do a few chunked calculations for a few instances and 
    saves the result in `outputs`, which is a memory shared dictionary.
    """
    for instance in instances:
        x = f(instance, big_matrix)
        outputs[instance] = x

def split_work(big_matrix, instances_to_calculate):
    """
    Split do_some_work into many processes by chunking instances_to_calculate, 
    creating a shared dictionary and spawning and joining the processes.
    """

    # break instance list into 4 chunks to pass each process
    instance_sets = np.array_split(instances_to_calculate, 4) 

    manager = Manager()
    outputs = manager.dict()

    processes = [
        Process(target=do_some_work, args=(big_matrix, instance_sets, outputs)) 
        for instances in instance_sets
    ]
    for p in processes:
        p.start()
    for p in processes:
        p.join()

    return user_sets, outputs

我的问题是:这样安全吗?我的函数f从不写任何东西,但我没有采取任何预防措施来共享进程之间的big_array,只是按原样传递它。 似乎正在工作但是我担心我是否可以通过在多个进程之间传递值来破坏任何东西,即使我从未写过它。

我尝试使用sharemem包在多个进程之间共享矩阵,但它似乎无法保存scipy稀疏矩阵,只能保存正常的numpy数组。

如果这不安全,我如何在进程之间共享(只读)大稀疏矩阵而没有问题?

我已经看到here我可以使用另一个指向同一内存的csc_matrix:

other_matrix = csc_matrix(
    (bit_matrix.data, bit_matrix.indices, bit_matrix.indptr), 
    shape=bit_matrix.shape, 
    copy=False
)

这会使它更安全,还是与传递原始物体一样安全?

感谢。

1 个答案:

答案 0 :(得分:1)

如解释here所示,您的第一个选项似乎是为每个进程创建一个稀疏矩阵的副本。这是安全的,但从性能的角度来看并不理想。但是,根据您在稀疏矩阵上执行的计算,开销可能不是很重要。

我怀疑使用multiprocessing lib的更清晰选项是创建三个列表(取决于您使用的矩阵格式),并使用valuesrow_ind和{{填充这些列表1)你的CSC矩阵。 col_ptr的{​​{3}}显示了如何使用multiprocessing或使用Array以及其中一种受支持的类型来完成此操作。

之后我不知道如何使用只读操作遇到麻烦,而且效率可能更高。