Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在新进程中执行python代码要比在主进程上慢得多_Python_Parallel Processing_Multiprocessing_Long Running Processes - Fatal编程技术网

在新进程中执行python代码要比在主进程上慢得多

在新进程中执行python代码要比在主进程上慢得多,python,parallel-processing,multiprocessing,long-running-processes,Python,Parallel Processing,Multiprocessing,Long Running Processes,我开始在python中学习multiprocessing,我注意到同一代码在主进程上的执行速度要比在使用multiprocessing模块创建的进程中快得多 这里是我的代码的简化示例,我首先在主进程上执行代码,并打印前10次计算的时间和总计算的时间。然后在新进程上执行相同的代码(这是一个长时间运行的进程,我可以随时发送新模式) 为什么执行时间会有这么大的差异?在这种情况下,您似乎在另一个进程中执行顺序执行,而不是并行化您的算法。这会产生一些开销 流程创建本身需要时间。但这还不是全部。您还可以在队

我开始在
python
中学习
multiprocessing
,我注意到同一代码在主进程上的执行速度要比在使用
multiprocessing
模块创建的进程中快得多

这里是我的代码的简化示例,我首先在
主进程上执行代码
,并打印前10次计算的时间和总计算的时间。然后在
新进程
上执行相同的代码(这是一个长时间运行的进程,我可以随时发送
新模式


为什么执行时间会有这么大的差异?

在这种情况下,您似乎在另一个进程中执行顺序执行,而不是并行化您的算法。这会产生一些开销

流程创建本身需要时间。但这还不是全部。您还可以在队列中传输数据,并使用Manager代理。这些实际上都是队列,或者实际上是两个队列和另一个进程。与使用内存中的数据拷贝相比,队列非常非常慢

如果您使用代码,在另一个进程中执行它,并使用队列来传输数据,那么它总是比较慢。这使得它从性能的角度来看毫无意义。尽管如此,可能还有其他原因需要这样做,例如,如果您的主程序需要执行其他操作,例如等待IO

如果你想提高性能,你应该创建几个进程来代替,并分割你的算法,这样你就可以在不同的进程中处理你范围内的部分,从而并行工作。如果你想让一组工作进程准备好等待更多的工作,你也可以考虑<代码>多进程。池< /代码>。这将减少流程创建开销,因为您只需执行一次。在Python3中,还可以使用
ProcessPoolExecutor


并行处理是有用的,但很少有蛇油能轻而易举地解决所有问题。为了最大限度地利用它,您需要重新设计您的程序,以最大限度地实现并行处理,并最大限度地减少队列中的数据传输

这有点微妙,但问题在于

new_pattern_for_processing = multiprocessing.Array('d', 10)
它不保存python
float
对象,它保存原始字节,在本例中足以保存10个8字节机器级别的
double
。在读取或写入此数组时,python必须将
float
转换为
double
,或者反过来。如果您正在读或写一次,这并不是什么大问题,但是您的代码在循环中多次这样做,并且这些转换占主导地位

为了确认这一点,我将机器级数组复制到了一个python浮点列表中,并让流程对此进行了处理。现在它的速度与父级相同。我的更改仅在一个功能中

def patt_recognition_new_process(old_patterns, new_pattern_on_new_proc, there_is_new_pattern, queue):
    print_count = 0
    while True:
        if there_is_new_pattern.value:
            local_pattern = new_pattern_on_new_proc[:]
            #START of same code on new process
            start_new_process_one_patt = time.time()
            #iterate_and_add(old_patterns, new_pattern_on_new_proc)
            iterate_and_add(old_patterns, local_pattern)
            if print_count < 10:
                print_count += 1
                print("Time on new process one pattern:", time.time() - start_new_process_one_patt)
            #END of same code on new process
            there_is_new_pattern.value = 0
            queue.put("DONE")
def patt_recognition_new_process(旧模式、新模式在新过程中、有新模式、队列):
打印计数=0
尽管如此:
如果存在新的模式值:
本地模式=新模式在新程序[:]
#在新进程上启动相同的代码
开始新的流程一次=时间时间()
#迭代和添加(旧模式、新模式和新过程)
迭代和添加(旧模式、本地模式)
如果打印计数小于10:
打印计数+=1
打印(“新流程一模式上的时间:”,Time.Time()-开始新流程一模式)
#新进程上相同代码的结束
有新的模式。值=0
queue.put(“完成”)

可能是由于
上下文切换的开销造成的?噢,谢谢!在过去的三天里我都快疯了。但我不完全理解它是如何比逐个访问元素更快地转换为列表的。你有关于这个问题的解释吗?:)这是外环。你做了很多次。当我创建这个列表时,我只有一次开销。现在我明白了。谢谢
new_pattern_for_processing = multiprocessing.Array('d', 10)
def patt_recognition_new_process(old_patterns, new_pattern_on_new_proc, there_is_new_pattern, queue):
    print_count = 0
    while True:
        if there_is_new_pattern.value:
            local_pattern = new_pattern_on_new_proc[:]
            #START of same code on new process
            start_new_process_one_patt = time.time()
            #iterate_and_add(old_patterns, new_pattern_on_new_proc)
            iterate_and_add(old_patterns, local_pattern)
            if print_count < 10:
                print_count += 1
                print("Time on new process one pattern:", time.time() - start_new_process_one_patt)
            #END of same code on new process
            there_is_new_pattern.value = 0
            queue.put("DONE")