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

时间:2015-06-22 07:41:07

标签: python multithreading python-3.x multiprocessing

我有一个程序,我正在进行多线程和多处理。但是在我最初的测试中,我发现老式的串行处理要么是多处理(使用更多CPU内核),要么是线程化(使用更多线程,例如CPU内核,但一次只能使用一个内核)!#/ p >

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

我的脚本遍历2个策略的列表。对于每个策略,它会遍历193个代码(stock_list)列表。

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

  1. 部分是正常的串行处理,只有一个CPU核心和一个线程。
  2. 部分是使用系统中所有可用CPU核心的多处理。
  3. Section是使用40个线程的队列来处理列表的线程。
  4. 在这个简单的测试脚本中,我没有对它们做任何想法,但只能睡0.01s pr。迭代让我感觉最快。

    Bly me,但看起来处理列表的老式串行方式比其他任何类型都快一点......! 我的测试结果显示了这些运行时间:

    1. 序列号:3.86s
    2. 多处理(核心)4.03s
    3. 多线程(线程)3.90s
    4. 我必须忽略这一点,并且必须在下面的代码中犯了错误。有多处理经验的人可以对这个难题有所了解。

      如何通过策略加快stock_list的处理速度,让这个示例代码以最快的速度运行?

      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))
      

2 个答案:

答案 0 :(得分:1)

通过在工作函数中使用lock,您是否会使代码或多或少地串行而不是多线程。需要吗?

如果使用一种策略分析代码不会影响其他策略,则无需使用锁定。

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

答案 1 :(得分:-1)

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

在这种情况下,Python线程不会并行运行。有一种称为全局解释器锁的东西阻止了这种情况。因此,没有加速,因为你现在在单线程的情况下做同样的等待,但也有很多任务切换和等待线程完成。

我不确定多处理变量的处理方式是什么,但我怀疑它是开销。你的榜样是相当人为的,不仅仅是因为你等待而不是做工作,还因为你不会等待很长时间。人们通常不会将多处理用于总共只需要四秒钟的事情......

作为一个脚注,我不明白你的主张只使用一个内核的主张是什么。 AFAIK,它不是python约束。

相关问题