Python 多处理/线程-被高估了,还是我遗漏了什么?

Python 多处理/线程-被高估了,还是我遗漏了什么?,python,multithreading,python-3.x,multiprocessing,Python,Multithreading,Python 3.x,Multiprocessing,我有一个程序,我正在制作多线程和多处理程序。但是在我最初的测试中,我发现老式的串行处理比多处理(使用更多的CPU内核)或线程(使用更多的线程或CPU内核,但一次只使用一个内核)都要好 为了说明这一点,我制作了这个简单的代码片段。在脚本的主要部分,我已标记了3种处理类型,因此您可以轻松选择所需的一种处理类型,并删除其他2个选项(删除完整部分以禁用该功能): 我的脚本迭代了两种策略的列表。对于每一种策略,它都会遍历193个股票代码列表(stock_list) 在主部分中,您可以选择要测试/采用的处理

我有一个程序,我正在制作多线程和多处理程序。但是在我最初的测试中,我发现老式的串行处理比多处理(使用更多的CPU内核)或线程(使用更多的线程或CPU内核,但一次只使用一个内核)都要好

为了说明这一点,我制作了这个简单的代码片段。在脚本的主要部分,我已标记了3种处理类型,因此您可以轻松选择所需的一种处理类型,并删除其他2个选项(删除完整部分以禁用该功能):

我的脚本迭代了两种策略的列表。对于每一种策略,它都会遍历193个股票代码列表(stock_list)

在主部分中,您可以选择要测试/采用的处理类型:

  • 部分是只有一个CPU内核和一个线程的正常串行处理
  • 第节是使用系统中所有可用CPU内核的多处理
  • 节正在使用40个线程的队列处理列表
  • 在这个简单的测试脚本中,我不想对它们做任何花哨的事情,但我只想通过0.01秒的pr迭代来感受哪一个是最快的

    我很高兴,但似乎用老式的串行方式处理列表比任何其他类型都要快一些。。。! 我的测试结果显示了以下运行时间:

  • 序列号:3.86s
  • 多处理(核心)4.03s
  • 多线程(线程)3.90s
  • 我一定没抓住重点,一定是在下面的代码中犯了错误。请有多重处理经验的人解释一下这个难题

    如何通过策略加快处理股票列表,并使示例代码尽可能以最快的速度运行

    import time
    import threading
    from threading import Thread, Lock
    from queue import Queue
    from multiprocessing import Pool
    from multiprocessing.dummy import Pool as ThreadPool
    
    start = time.time()     # Start script timer
    
    stock_list = ['aan', 'anf', 'ancx', 'ace', 'atvi', 'aet', 'agco', 'atsg', 'awh', 'all', 'afam', 'alj', 'dox', 'acas', 'afg', 'arii', 'asi', 'crmt', 'amkr', 'nly', 'anh', 'acgl', 'arw', 'aiz', 'atw', 'avt', 'axll', 'axs', 'blx', 'bkyf', 'bmrc', 'bku', 'banr', 'b', 'bbt', 'bbcn', 'bhlb', 'bokf', 'cjes', 'caci', 'cap', 'cof', 'cmo', 'cfnl', 'cacb', 'csh', 'cbz', 'cnbc', 'cpf', 'cvx', 'cb', 'cnh', 'cmco', 'cnob', 'cop', 'cpss', 'glw', 'crox', 'do', 'dds', 'dcom', 'dyn', 'ewbc', 'eihi', 'ebix', 'exxi', 'efsc', 'ever', 're', 'ezpw', 'ffg', 'fisi', 'fdef', 'fibk', 'nbcb', 'banc', 'frc', 'frf', 'fcx', 'gm', 'gco', 'gsol', 'gs', 'glre', 'hbhc', 'hafc', 'hdng', 'hcc', 'htlf', 'hele', 'heop', 'hes', 'hmn', 'hum', 'im', 'irdm', 'joy', 'jpm', 'kalu', 'kcap', 'kmpr', 'kss', 'lbai', 'lf', 'linta', 'lmca', 'lcut', 'lnc', 'lmia', 'mtb', 'mgln', 'mant', 'mpc', 'mcgc', 'mdc', 'taxi', 'mcc', 'mw', 'mofg', 'mrh', 'mur', 'mvc', 'myrg', 'nov', 'nci', 'navg', 'nni', 'nmfc', 'nnbr', 'nwpx', 'oln', 'ovti', 'olp', 'pccc', 'pre', 'pmc', 'psx', 'phmd', 'pjc', 'ptp', 'pnc', 'bpop', 'pfbc', 'pri', 'pl', 'rf', 'rnr', 'regi', 'rcii', 'rjet', 'rbcaa', 'sybt', 'saft', 'sasr', 'sanm', 'sem', 'skh', 'skyw', 'sfg', 'stt', 'sti', 'spn', 'sya', 'tayc', 'tecd', 'tsys', 'ticc', 'twi', 'titn', 'tol', 'tmk', 'twgp', 'trv', 'tcbk', 'trn', 'trmk', 'tpc', 'ucbi', 'unm', 'urs', 'usb', 'vlo', 'vr', 'voxx', 'vsec', 'wd', 'wres', 'wbco', 'wlp', 'wfc', 'wibc', 'xrx', 'xl']
    
    tickers = []
    strategies = []
    
    def do_multiproces_work(ticker):
        print(threading.current_thread().name,strategy,ticker)
        time.sleep(0.01)
    
    
    #==============================================================================
    # Threading
    
    # lock to serialize console output
    lock = Lock()
    
    def do_work(item):
    
        try:
    
            with lock: # This is where the work is done
                print(threading.current_thread().name,strategy,item)
                time.sleep(.01) # pretend to do some lengthy work.
    
        except Exception as e:
                print(str(e))
    
    # The worker thread pulls an item from the queue and processes it
    def worker():
        try:
            while True:
                item = q.get()
                do_work(item)
                q.task_done()
    
        except Exception as e:
                print(str(e))
    
    #==============================================================================
    
    if __name__ == '__main__':
    
        strategies = ['strategy0', 'strategy1']
        #==============================================================================
        # Strategies iteration
        #==============================================================================
        try:
            for strategy in strategies:
                ##=========================================================================
                ## Tickers iteration
                ##=========================================================================
               # 1. Normal Serial processing
                for ticker in stock_list:
                    do_multiproces_work(ticker)
    
                #==============================================================================
    #           # 2. Pure Multiprocessing (without multiple threads)
    #            '''
    #            pool = ThreadPool()
    #            # Sets the pool size, If you leave it blank,
    #            it will default to the number of Cores in your machine.
    #            '''
    #
    #            # Make the Pool of workers
    #            pool = ThreadPool()
    #
    #            # Do work and return the results
    #            # Multiproc. Without threading
    #            pool.map(do_work, stock_list)
    #
    #            #results = pool.map(urllib2.urlopen, urls)
    #
    #            #close the pool and wait for the work to finish
    #            pool.close()
    #            pool.join()
    
                #==============================================================================
    
    #            # 3. Threading (from only one processor core)
    #            # Create the queue and thread pool.
    #            global q
    #            q = Queue()
    #            for i in range(40):  # No of parallel threads/Queues - 40 et godt valg.
    #                 t = threading.Thread(target=worker)  # Kalder arb fct.
    #                 t.daemon = True  # thread dies when main thread (only non-daemon thread) exits.
    #                 t.start()
    #
    #            # stuff work items on the queue (in this case, just a number).
    #            for item in stock_list:  # INPUT LISTE TIL ANALYSE
    #                q.put(item)
    #
    #            q.join()       # block until all tasks are done
                #==============================================================================
        except Exception as e:
                print(str(e))
    
        # Stopping and printing result from script-timer
        seconds = time.time()-start
    
        m, s = divmod(seconds, 60)
        h, m = divmod(m, 60)
        print('Script finished in %.2f seconds' %(time.time()-start))
    

    通过在work函数中使用lock,可以使代码或多或少具有串行性,而不是多线程。需要吗

    如果使用一种策略分析股票代码不会影响其他策略,则无需使用lock


    只有当他们访问共享资源(例如文件或打印机)时才应使用锁。

    您没有指定,因此我假设您使用的是Python 2.7的C实现

    在这种情况下,Python线程不会并行运行。有一种称为全局解释器锁的东西可以防止这种情况。因此,对您来说没有加速,因为您现在执行与单线程情况相同的等待,但也有大量任务切换和等待线程完成

    我不确定处理多处理变量的方法是什么,但我怀疑这是开销。你的例子是相当做作的,不仅因为你等待而不是工作,而且因为你没有等待很长时间。通常情况下,对于总共只需要四秒钟的事情,不会使用多处理


    作为一个脚注,我不明白你所说的线程只使用一个内核是基于什么。好了,这不是python的限制。

    你为什么拿着锁睡觉?@cdarke,你能写下我的代码有哪些部分不是最佳的/有缺陷的,以及有哪些地方出了问题吗。不是在评论中而是在回答中?谢谢大卫。我不需要按照特定的顺序处理它们,所以不需要锁。我实际上使用的是Python3.3(WinPython2.3.4)64位。在配备Intel i7 CPU的机器上,4个内核,每个内核有2个线程。是的,我的例子是人为地简化了我的实际问题/代码。您通常希望在Stackoverflow上使用此选项。诚然,代码示例应该是最少的。然而,在我看来,你实际上是从这个例子中得出了关于性能的结论,我认为你不应该这样做。