медленный параллельный код в Python по сравнению с последовательной версией, почему он медленнее? - PullRequest
0 голосов
/ 14 июля 2020

Я создал две версии программы для сложения чисел массива: одна версия использует параллельное программирование, а другая - последовательное. Проблема в том, что я не могу заставить параллельную программу возвращать более быстрое время обработки. В настоящее время я использую Windows 8 и Python 3.x. Мой код:

from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor, as_completed
import random
import time

def fun(v):
    s=0
    for i in range(0,len(v)):
        s=s+l[i]
    return s

def sumSeq(v):
    s=0
    start=time.time()
    for i in range(0,len(v)):
        s=s+v[i]
    start1=time.time()
    print ("time seq ",start1-start," sum = ",s)

def main():
    workers=4
    vector = [random.randint(1,101) for _ in range(1000000)]
    sumSeq(vector)
    dim=(int)(len(vector)/(workers*10))
    s=0
      
    chunks=(vector[k:k+dim] for k in range(0,len(vector),(int)(len(vector)/(workers*10))))
    start=time.time()
    with ThreadPoolExecutor(max_workers=workers) as executor:
        futures=[executor.submit(fun,chunk) for chunk in chunks]
    
    start1=time.time()
    for future in as_completed(futures):
        s=s+future.result()
    
    print ("concurrent time ",start1-start," sum = ",s)

Проблема в том, что я получаю следующий ответ:

time sec  0.048101186752319336  sum =  50998349
concurrent time  0.059157371520996094  sum =  50998349

Я не могу заставить параллельную версию работать быстрее, я изменил размер фрагментов и количество максимальных рабочих к None, но ничего не работает. Что я делаю не так? Я читал, что проблема может заключаться в создании процессов, так как я могу это исправить простым способом?

Спасибо

1 Ответ

2 голосов
/ 14 июля 2020

Давняя слабость Python заключается в том, что он не может запускать чистый код Python одновременно в нескольких потоках; ключевое слово для поиска - "GIL" или "глобальная блокировка интерпретатора".

Способы решения этой проблемы:

  • Это применимо только к операциям с высокой нагрузкой на ЦП, таким как сложение; Операции ввода-вывода и т.п. могут успешно выполняться параллельно. Вы можете продолжать выполнять код Python в одном потоке, в то время как другие ждут диска, сети, базы данных и т. Д. c.
  • Это относится только к чистому коду Python; несколько модулей расширения, требующих больших вычислительных ресурсов, выпустят GIL и позволят запускать код в других потоках. Такие вещи, как матричные операции в numpy или операции с изображениями, могут, таким образом, выполняться в потоках вместе с потоком Python, загружающим процессор.
  • Это применимо конкретно к потокам (ThreadPoolExecutor); ProcessPoolExecutor будет работать так, как вы ожидаете, но он более изолирован, поэтому программа будет тратить больше времени на маршалинг и демаршалинг данных и промежуточных результатов.
* 1015 пример не очень хорошо подходит для этого теста:
  • Он слишком мал; с общим временем 0,05 с, большая часть этого времени будет связана с настройкой и отключением параллельного запуска. Чтобы проверить это, вам потребуется как минимум несколько секунд, в идеале несколько секунд или пара минут.
  • Последовательная версия посещает массив последовательно; такие вещи, как кэш ЦП, оптимизированы для такого доступа. Параллельная версия будет обращаться к фрагментам случайным образом, что может вызвать вытеснение кеша и т.п.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...