【问题标题】:Python defaultdict behavior possible with multiprocessing?多处理可能导致 Python defaultdict 行为?
【发布时间】:2012-02-22 07:32:26
【问题描述】:

我不确定这是否可能(希望如此)。我有一个数据集,我通过一个使用 defaultdict 的进程运行。 DefaultDict 有一个功能,如果你搜索的东西不在字典中,它就会被添加(在我的情况下,我正在搜索它们被添加的值,然后我稍后会搜索这些值,如果它们在字典中,那么我将值从默认的 false 设置为 True)。工作起来很容易,没有问题,但是一旦我尝试多处理它,我就会开始得到不正确的结果(真实的数据/过程非常大,而且我有多核硬件,所以为什么不使用它,对吧?)。这是我的结果(具有多进程的表的大小似乎总是在变化,有时没有多进程的情况相同,但通常略小。):

size of Table(with multiprocesing) is: 398
total number of true(with multiprocesing) is  0
size of Table(without multiprocesing) is  402
total number of true(without multiprocessing) is  250

无论如何,这里有一些功能代码。顶部是多处理代码,底部没有多处理(我想出了如何让 defaultdict 与所有新进程共享但仍然不起作用):

from multiprocessing import Pool
from multiprocessing.managers import BaseManager, DictProxy
from collections import defaultdict

class MyManager(BaseManager):
    pass

MyManager.register('defaultdict', defaultdict, DictProxy)

def test(i,x, T):
    target_sum = 100
    # T[x, i] is True if 'x' can be solved
    # by a linear combination of data[:i+1]
    #T = defaultdict(bool)           # all values are False by default
    T[0, 0] = True                # base case

    for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself
            #print s
            for c in range(s / x + 1):  
                if T[s - c * x, i]:
                    T[s, i + 1] = True


data = [2,5,8]                
pool = Pool(processes=2)
mgr = MyManager()
mgr.start()
T = mgr.defaultdict(bool)
T[0, 0] = True 
for i, x in enumerate(data):    # i is index, x is data[i]
    pool.apply_async(test, (i,x, T))
pool.close()
pool.join()
pool.terminate()


print 'size of Table(with multiprocesing) is:', len(T)
count_of_true = []
for x in T.items():
    if T[x] == True:
       count_of_true.append(x)
print 'total number of true(with multiprocesing) is ', len(count_of_true)


#now lets try without multiprocessing
target_sum = 100
# T[x, i] is True if 'x' can be solved
# by a linear combination of data[:i+1]
T1 = defaultdict(bool)           # all values are False by default
T1[0, 0] = True                # base case


for i, x in enumerate(data):    # i is index, x is data[i]
    for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself
            for c in range(s / x + 1):  
                if T1[s - c * x, i]:
                    T1[s, i + 1] = True

print 'size of Table(without multiprocesing) is ', len(T1)

count = []
for x in T1:
    if T1[x] == True:
        count.append(x)

print 'total number of true(without multiprocessing) is ', len(count)

我希望有一个解决方案。在过去的两周里,我尝试将它运行到数据库中,但是对于非常大的数据集来说它太慢了。上述过程处理内存中的所有内容(但仍然需要几个小时才能在我的测试数据上运行,这就是我想在其上使用多核的原因)。

【问题讨论】:

    标签: python multiprocessing


    【解决方案1】:

    defaultdict 的行为很容易使用标准的dict 进行复制。在这种情况下,在我看来您可以简单地替换 test 中的这一行:

    if T[s - c * x, i]:
    

    用这一行:

    if T.get((s - c * x, i), False):
    

    在费心定制 Manager 对象之前,看看您是否可以让此代码与标准字典一起使用。

    但实际上似乎i 的每个值都将存储可以被处理i + 1 的循环访问的值。这意味着每个循环的结果取决于前一个循环,因此异步方法可能会产生错误。

    要对此进行扩展,请尝试以下代码:

    from multiprocessing import Pool
    from multiprocessing.managers import BaseManager, DictProxy, ListProxy
    from collections import defaultdict
    
    class MyManager(BaseManager):
        pass
    
    MyManager.register('defaultdict', defaultdict, DictProxy)
    MyManager.register('list', list, ListProxy)
    
    def test(i,x,T, order):
        target_sum = 100
        # T[x, i] is True if 'x' can be solved
        # by a linear combination of data[:i+1]
        #T = defaultdict(bool)          # all values are False by default
        T[0, 0] = True                  # base case
        for s in range(target_sum + 1): # set the range of one higher 
                                        # than sum to include sum itself
            for c in range(s / x + 1):
                if T[s - c * x, i]:
                    T[s, i + 1] = True
                    order.append(i)
    
    def setup():
        mgr = MyManager()
        mgr.start()
        run_order = mgr.list()
        T = mgr.defaultdict(bool)
        T[0, 0] = True
        data = [2,5,8]
        return data, T, run_order
    
    def async_loop(data, func, output, run_order, wait=False):
        pool = Pool(processes=6)
        for i, x in enumerate(data):    # i is index, x is data[i]
            p=pool.apply_async(func, (i, x, output, run_order))
            if wait:
                p.wait()
        pool.close()
        pool.join()
        pool.terminate()
    
    def output_size(output, run_order, wait):
        wait = 'out' if wait else ''
        print 'size of Table (with{0} multiprocesing) is: {1}'.format(
            wait, len(output))
        count_of_true = []
        for (x, result) in output.items():
            if output[x] == True:
                count_of_true.append(x)
        print 'total number of true (with{0} multiprocesing) is: {1}'.format(
            wait, len(count_of_true))
        print 'run order is: {0}'.format(run_order)
    
    data, table, run_order = setup()
    async_loop(data, test, table, run_order, wait=True)
    output_size(table, run_order, True)
    data, table, run_order = setup()
    async_loop(data, test, table, run_order, wait=False)
    output_size(table, run_order, false)
    

    输出如下:

    size of Table (without multiprocesing) is: 402
    total number of true (without multiprocesing) is: 250
    run order is: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
    size of Table (with multiprocesing) is: 402
    total number of true (with multiprocesing) is: 250
    run order is: [0, 0, 0, 1, 1, 0, 1, 1, 0, 2, 1, 2, 2, 1, 0, 2, 1, 2, 2, 1, 1, 2, 2, 1, 2, 1, 0, 2, 1, 2, 1, 2, 1, 2, 0, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 0, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 0, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 0, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 0, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 0, 1, 2, 2, 1, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 0, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 0, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 0, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 0, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 0, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 0, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 0, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 0, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 2, 1, 2, 0, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 0, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 0, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 0, 2, 1, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 0, 2, 1, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 2, 1, 0, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 0, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 0, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 0, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 0, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 0, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 0, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 0, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 0, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 0, 1, 2, 2, 1, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 0, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 0, 1, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 2, 1, 0, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0]
    

    如您所见,如果您调用p.wait(),则执行顺序是连续的,如果您不调用,则执行顺序是无序的。并且由于它出现故障,您会注意到在 i = 1i = 2 计算开始之前,并非所有 i = 0 的计算都已完成。这有时可能意味着i = 0 计算写入i = 1 使用的密钥,但仅在i = 1 计算已经读取密钥之后。 (事实上​​,虽然在上面的例子中表格的长度相同,但您会注意到 order 列表的长度是不同的。所以 发生了一些不同的事情,即使它没有' t影响最终结果。)

    【讨论】:

    • 看起来很有趣。让我玩弄代码然后回复你。与此同时,我确实注意到了一些奇怪的事情,似乎以你的方式它只报告真正的条目(这是我需要的,所以它是完美的)但有时它似乎是 250(这是正确的)其他时候我注意到它在 248或 246. 知道我可以做些什么来解决不一致问题吗?
    • @Lostsoul,我想到的一件事是您可能必须在测试循环中执行if T.get(x, True):。但如果x 不在字典中,那将导致KeyError,所以这可能不是问题。此外,如果这与defaultdict 的行为相同,那么它可能是算法的问题,而不是defaultdict。我看看能不能找出问题所在。
    • 谢谢,我也会做一些挖掘来找出不一致的地方(因为两个算法完全相同)。话虽如此,我必须说你是个天才。您的方法效果很好,当它确实有效时,列表是相同的。最坏的情况是,我可以运行 multiprocessed 两次以确保没有遗漏任何内容,但老实说,如果我可以做一些简单的事情来确保结果一致,这似乎是一种浪费。
    • 仅供参考。我不确定这有多正确,但如果我在该程序运行时启动一堆程序,结果会有点不一致,这让我相信它可能是多处理。
    • @AlyShmahell 我上次看这个已经很久了,但据我所知,我的建议是使用默认字典,而是使用 get 和 setdefault “模拟”一个。这样你就不必处理这个问题了。我的答案中的代码不会尝试修复 defaultdict 问题。它只是演示了乱序执行的现象。
    【解决方案2】:

    我快速检查了一下,我怀疑,子进程正在创建它自己的 T 版本。您需要设置一个全局变量并让管理器更新该变量。

    我在测试函数中添加了这个以查看 id T 是什么:

    T[0, 0] = True                # base case
    filename = "test."+str(i)
    with open(filename,  "w" ) as f:
        f.write( "address of T %x\n" % id(T) )
    f.close()
    

    T 823f50 的地址 T 955550的地址 T 955bd0的地址

    所以当孩子完成时,父母永远不会得到更新。

    我会用它来设置一个全局或进程共享的字典。

    【讨论】:

    • multiprocessing 中,所有内容都被复制。但Tid 无关紧要,因为它只是真正dict 的代理,由Manager 对象管理。换句话说,T 一个进程共享的字典。
    • 正确,我看到 T 实际上是全局的,因为它的缩进位置。
    【解决方案3】:

    我修复了一些问题

    我从函数调用中删除了 T,这正在杀死你定义为 manager.defaultdict(bool) 的进程变量

    编辑:实际上,我刚刚意识到,T 是全局的,因为没有 def main,我将 T 恢复回函数调用。对于那个很抱歉。 :)

    编辑 2:我还在同步后添加了 p.wait()。我想这可能是你看到水滴的地方。我注意到了同样的下降,但添加 p.wait 看起来已经停止了孩子们的下降。

    编辑 3:将 p.wait() 更改为 p.get(timeout=5)

    您只需要传递函数参数,而不是全局变量。 此外,在您的循环中, T 完成后的结果是:

    T = defaultdict(, {(7, 3): True, (90, 0): False, ... 等})

    所以我更改了 for 循环以获取键值。

    表的大小(多处理)是:402 真(多处理)总数为 250 表的大小(没有多重处理)是 402 true(没有多处理)的总数是 250
        from multiprocessing import Pool
        from multiprocessing.managers import BaseManager, DictProxy
        from collections import defaultdict
    
        class MyManager(BaseManager):
            pass
    
        MyManager.register('defaultdict', defaultdict, DictProxy)
    
        def test(i,x,T):
            target_sum = 100
            # T[x, i] is True if 'x' can be solved
            # by a linear combination of data[:i+1]
            #T = defaultdict(bool)           # all values are False by default
            T[0, 0] = True                # base case
            for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself
                for c in range(s / x + 1):  
                    if T[s - c * x, i]:
                        T[s, i + 1] = True
    
    
    
        mgr = MyManager()
        mgr.start()
        T = mgr.defaultdict(bool)
    
        T[0, 0] = True 
        data = [2,5,8]                
        pool = Pool(processes=2)
    
        for i, x in enumerate(data):    # i is index, x is data[i]
            p=pool.apply_async(test,(i,x,T))
            p.get(timeout=5)
        pool.close()
        pool.join()
        pool.terminate()
    
        print 'size of Table(with multiprocesing) is:', len(T)
        count_of_true = []
        for (x, result) in T.items():
            if T[x] == True:
               count_of_true.append(x)
        print 'total number of true(with multiprocesing) is ', len(count_of_true)
    
        #==========================
        #now lets try without multiprocessing
        target_sum = 100
        # T[x, i] is True if 'x' can be solved
        # by a linear combination of data[:i+1]
        T1 = defaultdict(bool)           # all values are False by default
        T1[0, 0] = True                # base case
    
    
        for i, x in enumerate(data):    # i is index, x is data[i]
            for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself
                    for c in range(s / x + 1):  
                        if T1[s - c * x, i]:
                            T1[s, i + 1] = True
    
        print 'size of Table(without multiprocesing) is ', len(T1)
    
        count = []
        for x in T1:
            if T1[x] == True:
                count.append(x)
    
        print 'total number of true(without multiprocessing) is ', len(count)
    

    【讨论】:

    • "我还添加了..." 请不要在您自己的答案中添加 cmets。请更新完整答案。然后删除无用的评论。
    • @Rich,添加p.wait() 完全否定了多处理的意义。它确保每个进程按顺序执行,而不是同时执行。在test 的内部循环中添加print i 语句以了解我的意思。
    • @Lostsoul,我只想提请您注意,在每个循环的末尾添加 p.wait() 是可行的,因为它可以防止发生任何多处理。所以他的回答实际上会减慢你的计算速度(因为它不是并发的并且增加了多处理的开销)。
    • @senderle,我试过 p.get(timeout=5)。它似乎与 p.wait() 具有相同的效果。
    • 我尝试捕获进程,然后在循环外运行 p.get()。结果继续波动。我认为池进程是正确的 - 问题是测试函数中的循环 - 当一个线程检查一个值而另一个进程尚未计算该位置时,这可能是一个时间问题,导致结果不正确。该进程与 p.wait() 一起工作,因为正如您所说,进程 1 已完成,因此当进程 2 开始时该表是正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 2010-11-15
    相关资源
    最近更新 更多