多处理字符串的共享内存数组

时间:2018-02-11 02:48:16

标签: python multiprocessing ctypes

我试图对一些现有代码进行多处理,并且我发现使用Pool对进程进行数据的pickle / unpickling过慢。我认为,对于我的情况,Manager会遭遇同样的问题,因为它在幕后进行同样的腌制。

为了解决这个问题,我试图转移到共享内存阵列。为此,我需要一个字符串数组。似乎multiprocessing.Array支持ctypes.c_char_p,但我很难将其扩展为字符串数组。以下是我尝试过的很多事情中的一些。

#!/usr/bin/python
import ctypes
import multiprocessing as mp
import multiprocessing.sharedctypes as mpsc
import numpy

# Tested possible solutions
ver = 1
if 1==ver:
    strings = mpsc.RawArray(ctypes.c_char_p, (' '*10, ' '*10, ' '*10, ' '*10))
elif 2==ver:
    tmp_strings = [mpsc.RawValue(ctypes.c_char_p, ' '*10) for i in xrange(4)]
    strings = mpsc.RawArray(ctypes.c_char_p, tmp_strings)
elif 3==ver:
    strings = []
    for i in xrange(4):
        strings.append( mpsc.RawValue(ctypes.c_char_p, 10) )

def worker(args):
    snum, lenarg = args
    string = '%s' % snum
    string *= lenarg
    strings[snum] = string
    return string

# Main progam
data = [(i, numpy.random.randint(1,10)) for i in xrange(3)]
print 'Testing version ', ver
print
print 'Single process'
for x in map(worker, data):
    print '%10s : %s' % (x, list(strings))
print

print 'Multi-process'
pool = mp.Pool(3)
for x in pool.map(worker, data):
    print '%10s : %s' % (x, list(strings))
    print '            ', [isinstance(s, str) for s in strings]

请注意,我使用的是multiprocessing.sharedctypes,因为我不需要锁定,而且它应与multiprocessing.Array

完全互换

上面代码的问题是结果strings对象包含常规字符串,而不是来自mpsc.RawArray构造函数的共享内存字符串。使用版本1和版本2,您可以看到在处理过程(如预期)时数据如何被加扰。对我来说,版本3看起来最初是有效的,但你可以看到=只是将对象设置为常规字符串,而这适用于短测试,在较大的程序中它会产生问题。

似乎应该有一种方法来创建指针的共享数组,其中指针指向共享内存空间中的字符串。如果您尝试使用c_void_p类型对c_str_p类型进行初始化,则woocommerce_quantity_input_args类型会抱怨我还没有直接操作底层地址指针的运气。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:0)

首先,您的第三个解决方案不起作用,因为strings未被多处理部分更改,但已被单个流程部分修改。您可以通过评论单个流程部分进行检查。

其次,这个会起作用:

import ctypes
import multiprocessing as mp
import multiprocessing.sharedctypes as mpsc
import numpy

strings = [mpsc.RawArray(ctypes.c_char, 10) for _ in xrange(4)]

def worker(args):
    snum, lenarg = args
    string = '%s' % snum
    string *= lenarg
    strings[snum].value = string
    return string

# Main progam
data = [(i, numpy.random.randint(1,10)) for i in xrange(4)]

print 'Multi-process'
print "Before: %s" % [item.value for item in strings]
pool = mp.Pool(4)
pool.map(worker, data)
print 'After : %s' % [item.value for item in strings]

输出:

Multi-process
Before: ['', '', '', '']
After : ['0000000', '111111', '222', '3333']