没有';在Python中使用多处理时,无法获得预期的结果

没有';在Python中使用多处理时,无法获得预期的结果,python,multiprocessing,Python,Multiprocessing,运行以下代码后,预期输出应为: [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, 5000001

运行以下代码后,预期输出应为:

[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,操作系统:Win10

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)浮动:

32b浮点只有23+1位小数,对应于7位以上的位(24*log10(2)=7.22)

您的数字是8位,这意味着它们不能准确地存储在数组中,并将四舍五入到缺失位的最近倍数(因此为4位小数)。改为使用32位整数或64b浮点数组

如果您只是尝试将您的值直接以顺序代码存储在数组中(甚至不涉及多个进程),您可能已经意识到问题在于数组的定义(和类型代码),因为它表现出完全相同的行为

除此之外:

  • 数组是隐式锁定的,您永远不会读更新写,每个任务实际上只是设置自己的个人单元格,显式锁定是无用和冗余的
  • 您所做的只是一个简单的映射,为什么不使用
    Pool.map
    /
    Pool.imap
    ,甚至可能是
    Poo.imap\u无序的

您正在使用单精度(32b)浮动:

32b浮点只有23+1位小数,对应于7位以上的位(24*log10(2)=7.22)

您的数字是8位,这意味着它们不能准确地存储在数组中,并将四舍五入到缺失位的最近倍数(因此为4位小数)。改为使用32位整数或64b浮点数组

如果您只是尝试将您的值直接以顺序代码存储在数组中(甚至不涉及多个进程),您可能已经意识到问题在于数组的定义(和类型代码),因为它表现出完全相同的行为

除此之外:

  • 数组是隐式锁定的,您永远不会读更新写,每个任务实际上只是设置自己的个人单元格,显式锁定是无用和冗余的
  • 您所做的只是一个简单的映射,为什么不使用
    Pool.map
    /
    Pool.imap
    ,甚至可能是
    Poo.imap\u无序的

在尝试了许多可能的修复方法之后,我终于发现数组的类型是错误的。 您应该使用
array=array('i',20)
,而不是
f

输出:


在尝试了许多可能的修复方法之后,我终于发现数组的类型是错误的。 您应该使用
array=array('i',20)
,而不是
f

输出:


试过搜索吗?另请阅读关于在Windows上保护主代码的多处理文档基本上,您的代码的工作方式
数组
是在每个进程中本地定义的-您需要在受保护的主代码中定义它,并将其作为参数传递-有@barny的示例不正确,
多进程。阵列
是一个共享的同步阵列代理,它的存在是为了在多个进程之间安全共享。是否尝试搜索?另请阅读关于在Windows上保护主代码的多处理文档基本上,您的代码的工作方式
数组
是在每个进程中本地定义的-您需要在受保护的主代码中定义它,并将其作为参数传递-有@barny的示例不正确,
multiprocessing.Array
是一个共享的同步阵列代理,它的存在是为了在多个进程之间安全地共享。
array = Array('f', 20)
All subprocesses done.
[50000000, 50000001, 50000002, 50000003, 50000004, 50000005, 50000006, 50000007, 50000008, 50000009, 50000010, 50000011, 50000012, 50000013, 50000014, 50000015, 50000016, 50000017, 50000018, 50000019]