并行处理与运行多个python内核在python中是如何工作的?

并行处理与运行多个python内核在python中是如何工作的?,python,python-3.x,multithreading,parallel-processing,jupyter-notebook,Python,Python 3.x,Multithreading,Parallel Processing,Jupyter Notebook,我有一个用户定义的函数(UDF),需要一段时间才能运行——大约一天左右。此外,UDF需要重复应用于不同的数据集。具体来说,my函数打开一个数据集,编辑它,然后保存该数据集。它不会返回任何东西 最好的加速方法是什么?如果我像3台Jupyter笔记本一样打开,一次运行3台——每台都在不同的数据集上,会更好吗?或者使用多处理包进行并行处理会更好吗 我试着按照这里的指南:用于并行处理,但它不起作用。不想编辑我的原始UDF,我基本上只是创建了另一个名为loop()的用户定义函数,如下所示: def loo

我有一个用户定义的函数(UDF),需要一段时间才能运行——大约一天左右。此外,UDF需要重复应用于不同的数据集。具体来说,my函数打开一个数据集,编辑它,然后保存该数据集。它不会返回任何东西

最好的加速方法是什么?如果我像3台Jupyter笔记本一样打开,一次运行3台——每台都在不同的数据集上,会更好吗?或者使用
多处理
包进行并行处理会更好吗

我试着按照这里的指南:用于并行处理,但它不起作用。不想编辑我的原始UDF,我基本上只是创建了另一个名为
loop()
的用户定义函数,如下所示:

def loop( i ):
     UDF( i, <...some other args that are not dynamic...> )
执行代码后,我得到的回报是:

<multiprocessing.pool.MapResult at 0x18cb2975160>

我做错了什么?哪条路更好?我对所有这些编程的东西都是新手。很抱歉,由于我正在自学,我的术语已关闭。

Intro: 没有人能说服您不运行多个Jupyter内核,但是这样做的(糟糕的)性能可能会说服您不要将这种策略扩展到许多天的处理管道,除了一些爱好项目

使用池: 最新的python对多处理进行了优化,可以大规模地完成这项工作,但需要一些常识(CPU内核的数量不一定是产生“最佳性能”的最佳选择)设置,同样适用于影响任何通用代码执行的RAM大小、CPU缓存重用效率,其中影响很容易在运行时达到
3+(!)
-数量级)。由于远程进程中更好的资源管理,maxstasksparchild参数对于稳定的长期运行可能非常重要

我主张不要让故事复杂化,并保护您使用上下文包装器“fusing”进行多天的处理(崩溃是昂贵的):

来自多处理导入池的
,TimeoutError
通过;导入系统
通过;导入时间
#############################################################################
##“正确”-CPU内核的数量取决于(很多)工作类型
nPROCs=4#可配置,不要“过度订阅”CPU内核
def UDF(…):#工作发生在这里:o)
...
返回#无效/a程序类似UDF
def循环器(p=(-1,无)):#实用程序循环器
UDF(p[1])#具有静态参数的功
返回p[0]#返回一个“self.Signature”到self-present
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
#----------------------------------ApolofWorkProcesses——上下文管理器融合---
将池(进程=nPROCs)作为APOOlofWorkProcess:#启动nPROCs进程
#-------------------------------------------------------------------------------
resultObj=apoolofworkprocesss.map_async(#调度方法
UDF,#工作:需要完成的工作
[(数据集索引(i),#签名“id”
i#数据集部分
)对于数据集中的i
]#ITERABLE:已定义。
)
#------------------------------------------------------------------------------- 
#在这里,仍然在上下文融合中,我们有一个“resultObj”-对象
#这项工作正在进行中
#在“远程”中,进程与主进程异步__
#这意味着我们可以等待结果,并通过提问报告进展情况
秒=5
eMOD1=60
eMOD2=60
eCNT=0
rCNT=1
MASKr=“\n({2:})::INF[{1:>3d}.]:UDF({0:>2d},数据集[{0:>2d}])已完成\n”
MASKb=“\n\nUSR:是的,先生,正如您所希望的那样,在{0:}UDF()调用报告到目前为止已经完成之后,将打破循环。其余的可能仍然来自Pool()-实例的resultObj,使用.get()-方法”
MASK0=“\u0”
MASK1=“”
MASK2=“{0:}:{1:}{2:}”。格式((eMOD1-1)*chr(8),
(eMOD1-1)*MASK0,
(eMOD1-1)*chr(8)
)
MASK3=“{0:}{1:}{2:}”。格式((eMOD2-1)
+eMOD1-1)*chr(8),
(eMOD1-1)*MASK0+(eMOD2-1)*chr(32),
(2-1)
+eMOD1-1)*chr(8)
)
打印“\n{0:}可以使用(Ctrl+C)退出此结果等待循环器”。格式(time.ctime())
尽管如此:
尝试:
打印(MASKr.format)(
resultObj.get(timeout=SECs),#要么在获取“id”时打印()-s,要么在SECs超时后抛出EXC:
rCNT,#rCNT计数器
time.ctime()#.ctime()时间戳
)
)
rCNT+=1#INC返回结果计数器
继续#从.get()循环等待结果
除TimeoutError外:#------------------------------------EXC应为普通超时事件
################超时
<multiprocessing.pool.MapResult at 0x18cb2975160>
from multiprocessing import Pool, TimeoutError
pass;                import sys
pass;                import time
#############################################################################
#                       # The "right"-amount of CPU-cores depends (a LOT) on type of work
nPROCs = 4              # configurable, do not "over-subscribe" the CPU-cores

def UDF( ... ):                   # The Work takes place here :o)
    ...
    return                        # void / a PROCEDURE-alike UDF

def looper( p = ( -1, None ) ):   # the utility-LOOP-er
    UDF(    p[1], <...> )         # the Work, having static parameters
    return  p[0]                  # RETs a "self.Signature" to self-present


if __name__ == '__main__':
    #----------------------------------aPoolOfWorkPROCESSes----CONTEXT-MANAGER-fusing---
    with Pool( processes = nPROCs ) as aPoolOfWorkPROCESSes: # start nPROCs processes
        #-------------------------------------------------------------------------------<BEGIN>
        resultObj = aPoolOfWorkPROCESSes.map_async(              # method of scheduling
                                         UDF,                    # JOB: a Work to be done
                                         [ ( dataset.index( i ), #   signature "id"
                                                            i    #   dataset-part
                                             )          for i in     dataset
                                           ]                     # ITERABLE: defined.
                                         )
        #------------------------------------------------------------------------------- 
        # here, still inside the context-fusing, we have a "resultObj"-Object
        #                                       the work is being performed
        #                                       in "remote"-processes async to __main__
        # that means we can stay waiting for results and report progress by asking

        SECs  =  5
        eMOD1 = 60
        eMOD2 = 60
        eCNT  =  0
        rCNT  =  1
        MASKr = "\n( {2:} ):: INF[{1:>3d}.]: UDF( {0:>2d}, dataset[{0:>2d}] ) has completed\n"
        MASKb = "\n\nUSR: yes, Sir, going to break the loop, as you wished after {0:} UDF() calls reported to finish so far. The rest may still arrive from Pool()-instance's resultObj, using the .get()-method"
        MASK0 = "_"
        MASK1 = "."
        MASK2 = "{0:}:{1:}{2:}".format( ( eMOD1 - 1 ) * chr( 8 ),
                                        ( eMOD1 - 1 ) * MASK0,
                                        ( eMOD1 - 1 ) * chr( 8 )
                                        )
        MASK3 = "{0:}|{1:}{2:}".format( ( eMOD2 - 1
                                        + eMOD1 - 1 ) * chr( 8 ),
                                        ( eMOD1 - 1 ) * MASK0 + ( eMOD2 - 1 ) * chr( 32 ),
                                        ( eMOD2 - 1
                                        + eMOD1 - 1 ) * chr( 8 )
                                        )
        print "\n{0:} may use (Ctrl+C) to exit from this result-awaiting looper".format( time.ctime() )
        while True:
              try:
                   print( MASKr.format(
                                resultObj.get( timeout = SECs ), # either print()-s, as it gets "id", or throws EXC: after SECs-timeout
                                rCNT,                            #              rCNT     counter
                                time.ctime()                     #              .ctime() timestamp
                                )
                          )
                   rCNT += 1                                     # .INC returned results counter
                   continue                                      # LOOP-waiting  results from .get()

              except                TimeoutError: #----------------------------- EXC expected, a plain elapsed timeout event
                   ################ TimeoutError handler:
                   # we expect this TimeoutError to happen quite often, each SECs-timeout seconds
                   eCNT +=1       # TimeoutError counter .INC-ed
                   sys.stdout.write(                                          MASK1
                                     if ( 0 < eCNT %   eMOD1 )           else MASK2
                                     if ( 0 < eCNT % ( eMOD1 * eMOD2 ) ) else MASK3
                                     )
                   sys.stdout.flush()                            # enforce the terminal UI-update

              except KeyboardInterrupt: #--------------------------------------- EXC-type expected, user hits Ctrl+C
                   print( MASKb.format( rCNT-1 ) )               # we used Ctrl+C to stop the loop
                   break                                         # terminate the while()-loop

              except: #--------------------------------------------------------- EXC-type unexpected, re-raised from a "remote"-process call via a .get()-method above
                   print( "\nEXC from a 'remote'-process" )      # we might have got a re-thrown EXC from a "remote"-process, via .get()-method
                   continue                                      # LOOP-waiting  results from .get()

        print "\n{0:} used (Ctrl+C) to request an exit from result-awaiting looper - remaining results still may become available from 'remote'-process(es) via calls to the resultObj.get() method".format( time.ctime() )
        #-------------------------------------------------------------------------------<END>
    #----------------------------------aPoolOfWorkPROCESSes----CONTEXT-MANAGER-fusing---
    print( 60*"/\\" )