Python проблемы производительности многопроцессорных - PullRequest
1 голос
/ 30 марта 2020

Я создал backtester в python, который выполняет полный цикл за 70 мс. В одном потоке (используя для l oop) я могу запустить этот backtester, и он показывает нормальную производительность (около 70 мс на итерацию):

for q in queue:
    print(backtest(alldata1h, alldata, q['strats'], q['filts']))

Моя проблема заключается в следующем: всякий раз, когда я пытаюсь Запустите эту функцию, используя многопроцессорность, производительность будет намного хуже (~ 800 мс на тестирование на истории).

Я пытался сделать это, используя массив объектов Process и Queue:

def do_workload(q, wk, a1h, ad):
    for w in wk:
        c = backtest(a1h, ad, w['strats'], w['filts'])
        q.put({"Strategy": w['sname'], "Filter": w['fname'], "c": c})
    q.put('DONE')

#Please ignore unnecessary indentation

    for i in range(thread_nr):
        thread_pool.append({"Process": "", "Queue": "", "workload": workloads[i], "workindex": 0, "finished": False})
        thread_pool[i]['Queue'] = Queue()
        thread_pool[i]['Process'] = Process(target=do_workload, args=(thread_pool[i]['Queue'], workloads[i], alldata1h, alldata))
        thread_pool[i]['Process'].start()
    print("Total workload: {} backtests".format(len(queue)))

    while queue_index < len(queue):
        for t in range(len(thread_pool)):
            time.sleep(0.1)
            if thread_pool[t]['finished'] == False:
                while not thread_pool[t]['Queue'].empty():
                    res = thread_pool[t]['Queue'].get()
                    if res == "DONE":
                        thread_pool[t]['finished'] = True
                    else:
                        final_results = final_results.append(res, ignore_index=True)
                        queue_index += 1
        print("Read from threads: {}/{}".format(queue_index, len(queue)))
        time.sleep(10)
    print("DONE")

, и я также попробовал это, используя объект Pool:

print("Total workload: {} backtests".format(len(queue)))
from functools import partial
target = partial(do_workload, a1h=alldata1h, ad=alldata)
pool = Pool(processes=thread_nr)
print("Starting pool...")
print(len(pool.map(target, workloads, len(workloads[0]))))

Мой процессор имеет 64 ядра и 128 потоков, поэтому я дал ему высокое значение thread_nr (около 100-120), но производительность по-прежнему ужасна.

Мой вопрос заключается в следующем: есть ли способ улучшить python достаточную многопроцессорность, чтобы достичь 70 мс на тестирование на секунду (на процесс)? Или я должен переписать весь проект (backtester и менеджер процессов) на C ++, чтобы добиться максимальной производительности (используя все возможные потоки / весь процессор).

...