Python 多处理/线程-被高估了,还是我遗漏了什么?
我有一个程序,我正在制作多线程和多处理程序。但是在我最初的测试中,我发现老式的串行处理比多处理(使用更多的CPU内核)或线程(使用更多的线程或CPU内核,但一次只使用一个内核)都要好 为了说明这一点,我制作了这个简单的代码片段。在脚本的主要部分,我已标记了3种处理类型,因此您可以轻松选择所需的一种处理类型,并删除其他2个选项(删除完整部分以禁用该功能): 我的脚本迭代了两种策略的列表。对于每一种策略,它都会遍历193个股票代码列表(stock_list) 在主部分中,您可以选择要测试/采用的处理类型:Python 多处理/线程-被高估了,还是我遗漏了什么?,python,multithreading,python-3.x,multiprocessing,Python,Multithreading,Python 3.x,Multiprocessing,我有一个程序,我正在制作多线程和多处理程序。但是在我最初的测试中,我发现老式的串行处理比多处理(使用更多的CPU内核)或线程(使用更多的线程或CPU内核,但一次只使用一个内核)都要好 为了说明这一点,我制作了这个简单的代码片段。在脚本的主要部分,我已标记了3种处理类型,因此您可以轻松选择所需的一种处理类型,并删除其他2个选项(删除完整部分以禁用该功能): 我的脚本迭代了两种策略的列表。对于每一种策略,它都会遍历193个股票代码列表(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))
通过在work函数中使用lock,可以使代码或多或少具有串行性,而不是多线程。需要吗 如果使用一种策略分析股票代码不会影响其他策略,则无需使用lock
只有当他们访问共享资源(例如文件或打印机)时才应使用锁。您没有指定,因此我假设您使用的是Python 2.7的C实现 在这种情况下,Python线程不会并行运行。有一种称为全局解释器锁的东西可以防止这种情况。因此,对您来说没有加速,因为您现在执行与单线程情况相同的等待,但也有大量任务切换和等待线程完成 我不确定处理多处理变量的方法是什么,但我怀疑这是开销。你的例子是相当做作的,不仅因为你等待而不是工作,而且因为你没有等待很长时间。通常情况下,对于总共只需要四秒钟的事情,不会使用多处理
作为一个脚注,我不明白你所说的线程只使用一个内核是基于什么。好了,这不是python的限制。你为什么拿着锁睡觉?@cdarke,你能写下我的代码有哪些部分不是最佳的/有缺陷的,以及有哪些地方出了问题吗。不是在评论中而是在回答中?谢谢大卫。我不需要按照特定的顺序处理它们,所以不需要锁。我实际上使用的是Python3.3(WinPython2.3.4)64位。在配备Intel i7 CPU的机器上,4个内核,每个内核有2个线程。是的,我的例子是人为地简化了我的实际问题/代码。您通常希望在Stackoverflow上使用此选项。诚然,代码示例应该是最少的。然而,在我看来,你实际上是从这个例子中得出了关于性能的结论,我认为你不应该这样做。