我有一个程序,我正在进行多线程和多处理。但是在我最初的测试中,我发现老式的串行处理要么是多处理(使用更多CPU内核),要么是线程化(使用更多线程,例如CPU内核,但一次只能使用一个内核)!#/ p >
为了说明我制作了这个简单的代码片段。在脚本的主要部分中,我标记了3种类型的处理,因此您可以轻松选择所需的处理类型,并删除其他2个选项(删除完整部分以禁用该功能):
我的脚本遍历2个策略的列表。对于每个策略,它会遍历193个代码(stock_list)列表。
在主要部分中,您可以选择要测试/使用的处理类型:
在这个简单的测试脚本中,我没有对它们做任何想法,但只能睡0.01s pr。迭代让我感觉最快。
Bly me,但看起来处理列表的老式串行方式比其他任何类型都快一点......! 我的测试结果显示了这些运行时间:
我必须忽略这一点,并且必须在下面的代码中犯了错误。有多处理经验的人可以对这个难题有所了解。
如何通过策略加快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))
答案 0 :(得分:1)
通过在工作函数中使用lock,您是否会使代码或多或少地串行而不是多线程。需要吗?
如果使用一种策略分析代码不会影响其他策略,则无需使用锁定。
只有在访问共享资源(例如文件或打印机)时才能使用锁。
答案 1 :(得分:-1)
您没有指定,因此我假设您正在使用Python 2.7的C实现。
在这种情况下,Python线程不会并行运行。有一种称为全局解释器锁的东西阻止了这种情况。因此,没有加速,因为你现在在单线程的情况下做同样的等待,但也有很多任务切换和等待线程完成。
我不确定多处理变量的处理方式是什么,但我怀疑它是开销。你的榜样是相当人为的,不仅仅是因为你等待而不是做工作,还因为你不会等待很长时间。人们通常不会将多处理用于总共只需要四秒钟的事情......
作为一个脚注,我不明白你的主张只使用一个内核的主张是什么。 AFAIK,它不是python约束。