运行以下代码后,预期输出应该是:
[50000000.0, 50000001.0, 50000002.0, ... 50000020.0], but now the result is weird
[50000000.0, 50000000.0, 50000000.0, 50000004.0, 50000004.0, 50000004.0, 50000008.0, 50000008.0, 50000008.0, 50000008.0, 50000008.0, 50000012.0, 50000012.0, 50000012.0, 50000016.0, 50000016.0, 50000016.0, 50000016.0, 50000016.0, 50000020.0]
我的代码有什么问题吗?Python:3.7.4,操作系统:win 10
from multiprocessing import Pool, Lock, Array, Queue
import os, time
array = Array('f', 20)
lock = Lock()
def long_time_task(i):
print('Run task %s (%s)...' % (i, os.getpid()))
start = time.time()
total_count = 0
for k in range(5*10**7): total_count += 1
total_count += i
lock.acquire()
array[i] = total_count
lock.release()
end = time.time()
print('Task %s runs %0.2f seconds.' % (i, (end - start)))
def init(l,a):
global lock
global array
lock = l
array = a
def mainFunc():
print('Parent process %s.' % os.getpid())
p = Pool(initializer=init, initargs=(lock,array))
for i in range(20): p.apply_async(long_time_task, args=(i,))
print('Waiting for all subprocesses done...')
p.close()
p.join()
print('All subprocesses done.')
if __name__ == '__main__':
mainFunc()
print(array[:])
您使用的是单精度(32b(浮点:
array = Array('f', 20)
32b浮点只有23+1位小数,这对应于7位以上的位(24*log10(2(=7.22(。
你的数字是8位数字,这意味着它们不能准确地存储在你的数组中,并且会四舍五入到缺失位的最接近倍数(因此是小数点后4位(。请改用32位整数或64b浮点数组。
如果您只是试图将值直接以顺序代码存储在数组中(甚至不涉及多个进程(,因为它表现出完全相同的行为,那么您可能已经意识到问题在于数组的定义(和类型代码(。
除此之外:
- 数组被隐式锁定,你永远不会读更新写,每个任务实际上只是设置自己的个人单元格,显式锁定是无用和多余的
- 你正在做的是一个琐碎的映射,为什么不使用
Pool.map
/Pool.imap
,甚至可能使用Poo.imap_unordered
在尝试了许多可能的修复方法之后,我终于发现数组的类型是错误的。您应该使用array = Array('i', 20)
,而不是f
输出:
All subprocesses done.
[50000000, 50000001, 50000002, 50000003, 50000004, 50000005, 50000006, 50000007, 50000008, 50000009, 50000010, 50000011, 50000012, 50000013, 50000014, 50000015, 50000016, 50000017, 50000018, 50000019]