Как увеличить скорость выполнения программы в python

Я выполняю вложенный цикл в python, который приведен ниже. Это служит основным способом поиска по существующим финансовым временным рядам и поискам периодов в временных рядах, которые соответствуют определенным характеристикам. В этом случае существуют два отдельных массива одинакового размера, представляющие «близкие» (например, стоимость актива) и «объем» (т.е.

Объем актива, который был обменен за период). Для каждого периода времени я хотел бы смотреть на все будущие интервалы с длинами от 1 до INTERVAL_LENGTH и посмотреть, соответствуют ли какие-либо из этих интервалов характеристикам, которые соответствуют моему поиску (в этом случае отношение значений закрытия больше 1,0001 и менее чем 1,5, а суммарный объем больше 100). Я понимаю, что одной из основных причин ускорения при использовании NumPy является то, что интерпретатору не нужно вводить проверки операндов каждый раз, когда он что-то оценивает, пока вы работаете в массиве в целом (например, numpy_array * 2), но, очевидно, код ниже не использует это. Есть ли способ заменить внутренний цикл на какую-то функцию окна, которая может привести к ускорению или любому другому способу, использующему numpy/scipy, чтобы ускорить это по существу на родном питоне? Альтернативно, есть ли лучший способ сделать это вообще (например, будет ли намного быстрее писать этот цикл на С++ и использовать переплетение)?

ТОП способов Ускорить Код Python. На примере построения Фрактала Мандельброта в Pygame


ARRAY_LENGTH = 500000 INTERVAL_LENGTH = 15 close = np.array( xrange(ARRAY_LENGTH) ) volume = np.array( xrange(ARRAY_LENGTH) ) close, volume = close.astype(‘float64’), volume.astype(‘float64’) results = [] for i in xrange(len(close) — INTERVAL_LENGTH): for j in xrange(i+1, i+INTERVAL_LENGTH): ret = close[j] / close[i] vol = sum( volume[i+1:j+1] ) if ret > 1.0001 and ret < 1.5 and vol >100: results.append( [i, j, ret, vol] ) print results
erich 17 июнь 2010, в 23:22
Поделиться
Ваш расчет выглядит очень просто, почему бы вам не использовать Cython?
Tarantula 17 июнь 2010, в 21:19

Поделиться:

3 ответа

Лучший ответ

Обновление: (почти) полностью векторизованная версия ниже в «new_function2».

Я добавлю комментарии, чтобы немного объяснить это.

Это дает 50-кратное ускорение, и более быстрое ускорение возможно, если вы в порядке с выходом, состоящим из массивов numpy вместо списков. Как есть:

In [86]: %timeit new_function2(close, volume, INTERVAL_LENGTH) 1 loops, best of 3: 1.15 s per loop

Вы можете заменить свой внутренний цикл на вызов np.cumsum(). См. мою функцию «new_function» ниже. Это дает значительное ускорение.

In [61]: %timeit new_function(close, volume, INTERVAL_LENGTH) 1 loops, best of 3: 15.7 s per loop
In [62]: %timeit old_function(close, volume, INTERVAL_LENGTH) 1 loops, best of 3: 53.1 s per loop

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

import numpy as np ARRAY_LENGTH = 500000 INTERVAL_LENGTH = 15 close = np.arange(ARRAY_LENGTH, dtype=np.float) volume = np.arange(ARRAY_LENGTH, dtype=np.float) def old_function(close, volume, INTERVAL_LENGTH): results = [] for i in xrange(len(close) — INTERVAL_LENGTH): for j in xrange(i+1, i+INTERVAL_LENGTH): ret = close[j] / close[i] vol = sum( volume[i+1:j+1] ) if (ret > 1.0001) and (ret < 1.5) and (vol >100): results.append( (i, j, ret, vol) ) return results def new_function(close, volume, INTERVAL_LENGTH): results = [] for i in xrange(close.size — INTERVAL_LENGTH): vol = volume[i+1:i+INTERVAL_LENGTH].cumsum() ret = close[i+1:i+INTERVAL_LENGTH] / close[i] filter = (ret > 1.0001) 1.5) 100) j = np.arange(i+1, i+INTERVAL_LENGTH)[filter] tmp_results = zip(j.size * [i], j, ret[filter], vol[filter]) results.extend(tmp_results) return results def new_function2(close, volume, INTERVAL_LENGTH): vol, ret = [], [] I, J = [], [] for k in xrange(1, INTERVAL_LENGTH): start = k end = volume.size — INTERVAL_LENGTH + k vol.append(volume[start:end]) ret.append(close[start:end]) J.append(np.arange(start, end)) I.append(np.arange(volume.size — INTERVAL_LENGTH)) vol = np.vstack(vol) ret = np.vstack(ret) J = np.vstack(J) I = np.vstack(I) vol = vol.cumsum(axis=0) ret = ret / close[:-INTERVAL_LENGTH] filter = (ret > 1.0001) 1.5) 100) vol = vol[filter] ret = ret[filter] I = I[filter] J = J[filter] output = zip(I.flat,J.flat,ret.flat,vol.flat) return output results = old_function(close, volume, INTERVAL_LENGTH) results2 = new_function(close, volume, INTERVAL_LENGTH) results3 = new_function(close, volume, INTERVAL_LENGTH) # Using sets to compare, as the output # is in a different order than the original function print set(results) == set(results2) print set(results) == set(results3)
Joe Kington 18 июнь 2010, в 02:05

Поделиться

⚡ УСКОРЯЕМ PYTHON в 20 РАЗ! | Новый способ :3

Одним из ускорений будет удаление части sum , так как в этой реализации она суммирует список длиной от 2 до INTERVAL_LENGTH . Вместо этого просто добавьте volume[j+1] к предыдущему результату vol из последней итерации цикла. Таким образом, вы просто добавляете два целых числа каждый раз вместо того, чтобы суммировать весь список и нарезать его каждый раз. Кроме того, вместо того, чтобы начать с выполнения sum(volume[i+1:j+1]) , просто сделайте vol = volume[i+1] + volume[j+1] , так как вы знаете, что начальный случай здесь всегда будет всего двумя индексами.

Другим ускорением будет использование .extend вместо .append , поскольку реализация python имеет extend работает значительно быстрее.

Вы также можете разбить окончательный оператор if , чтобы при необходимости выполнять только определенные вычисления. Например, вы знаете if vol

Это не отвечает на вашу проблему точно, но я думаю, что в особенности с проблемой суммы вы должны увидеть значительные ускорения с этими изменениями.

Читайте также:
Как переехать по программе

Изменить — вам также не нужно len , поскольку вы знаете конкретно длину списка уже (если только это не было только для примера). Определение его как числа, а не len(something) всегда быстрее.

Изменить — реализация (это не проверено):

ARRAY_LENGTH = 500000 INTERVAL_LENGTH = 15 close = np.array( xrange(ARRAY_LENGTH) ) volume = np.array( xrange(ARRAY_LENGTH) ) close, volume = close.astype(‘float64’), volume.astype(‘float64’) results = [] ex = results.extend for i in xrange(ARRAY_LENGTH — INTERVAL_LENGTH): vol = volume[i+1] for j in xrange(i+1, i+INTERVAL_LENGTH): vol += volume[j+1] if vol > 100: ret = close[j] / close[i] if 1.0001 < ret < 1.5: ex( [i, j, ret, vol] ) print results
nearlymonolith 17 июнь 2010, в 23:08
Поделиться

Другим ускорением было бы определить extend_results=results.extend» once (before the loop) and then using exte_results ([i, j, ret, vol])` внутри цикла, чтобы избежать поиска. Но всегда timeit (с timeit модуля timeit при оптимизации )!

ChristopheD 17 июнь 2010, в 21:34

Интересно! Насколько значительным является время поиска? Это обычно полезное ускорение, или это больше из-за величины этого конкретного цикла?

nearlymonolith 17 июнь 2010, в 21:43
ChristopheD 17 июнь 2010, в 22:09
John Machin 17 июнь 2010, в 23:13
Спасибо! Я внес изменения — хотя 1.0001 1.0001 и ret
nearlymonolith 17 июнь 2010, в 23:22

Я почти уверен, что здесь есть проблема с вычислением vol . Срез от i + 1: j + 1 в исходном коде, и j начинается с i + 1. Для меня это означает, что vol должен быть инициализирован равным 0, а volume[j] добавлен для каждой итерации в цикле, а не для volume[j+1] .

Justin Peel 18 июнь 2010, в 14:26
Показать ещё 4 комментария

Почему бы вам не попытаться сгенерировать результат как один список (намного быстрее, чем добавлять или расширять), например:

results = [ t for t in ( (i, j, close[j]/close[i], sum(volume[i+1:j+1])) for i in xrange(len(close)-INT_LEN) for j in xrange(i+1, i+INT_LEN) ) if t[3] > 100 and 1.0001 < t[2] < 1.5 ]
Nas Banov 18 июнь 2010, в 05:20
Поделиться

Ещё вопросы

  • 0 Как исчезнуть элемент при переходе?
  • 1 Общие методы приводят это к T
  • 0 Как добавить правило в редактор RichText с помощью плагина jquery.validate.js?
  • 0 Можно ли загрузить данные изображения и отобразить в html со скрытым URL-адресом src
  • 0 Как импортировать js-файл в mvc
  • 0 Как издеваться над угловым сервисным методом, который принимает параметр
  • 0 происхождение функции javascript [дубликаты]
  • 1 Основы математики на Java
  • 1 Подпись по java и openssl не совпадает
  • 0 Как показать ошибки в окнах оповещений после нажатия кнопки отправки с помощью угловых JS?
  • 1 Пользовательский диктант с хешируемыми ключами не может обрабатывать рекурсивные структуры
  • 0 Как разделить библиотеку между процессом и вызываемым скриптом, используя SWIG?
  • 1 Как проверить массив на возможные делители?
  • 1 Версия Bump Gradle без столкновения с версией Android Gradle Plugin
  • 0 Ошибка Zend Framework 2: оператор не может быть выполнен при реализации функции year в табличном шлюзе
  • 0 Скрипт запуска Drupal jQuery для .resize ()
  • 1 Как установить адаптеры вложенных представлений рециркулятора при использовании привязки данных?
  • 0 В mysql Как узнать количество воскресений за месяц
  • 1 Вызов процесса в C # со строковыми аргументами []
  • 0 Изменить прозрачность другой вкладки при наведении курсора на текущую вкладку
  • 0 Таблица отношений не обновляется, когда я вставляю записи
  • 1 Xamarin Profiler вылетает приложение с самого начала
  • 0 стиль шоу отличается в Chrome и Firefox Safari и iPhone
  • 1 Python 3 — Сокращение списка путем циклического восстановления данного набора
  • 0 Отладка в Visual Studio — могу ли я увидеть код библиотеки Intel Compiler?
  • 0 Как узнать, есть ли у элемента другой элемент внутри его класса
  • 1 Отсутствие практического понимания использования Play + Scala против JavaScript
  • 1 Фильтр DataGridView скрывает отредактированные элементы
  • 1 Robolectric Unit Test завершается неудачно с NoClassDefFoundError, когда приложение зависит от AppsFlyerLib
  • 0 Добавить или удалить класс Css, когда входное значение равно нулю или не равно нулю
  • 1 Способы уменьшения глубины рекурсии в Python
  • 0 Как подключиться к серверу sql используя php в xampp
  • 1 Как читать данные скрытой формы в функции Flask
  • 1 Java jar-файл не может найти .dll с jna.jar
  • 1 Как определить, что для fillStyle был назначен недопустимый цвет?
  • 0 Преобразовать целые числа в символы [дубликаты]
  • 1 Захват сообщения окна и затем запуск кода
  • 1 Интерфейс между контроллером и сервисным уровнем
  • 1 Словарь головоломки
  • 1 Высокая производительность в многозадачности внутри Tomcat
  • 0 Как реализовать скриптовые события для дизайна видеоигр?
  • 1 Сортировать список на основе другого списка
  • 1 Разбор XML и сохранение результатов в строке
  • 0 Замена строкового значения в PHP
  • 1 xna c # перехватить и отменить кнопку закрытия окна (x) и Ctrl F4
  • 1 Найдите топ-3 в столбцах данных, используя панд
  • 0 Почему я не могу использовать службу $ http в разрешении маршрута?
  • 1 Какие версии Android NDK поддерживают 64-разрядные архитектуры?
  • 0 Веб-браузер компилирует элементы CSS в алфавитном порядке
  • 1 Как определить, попадает ли данная дата в следующую неделю / месяц

Источник: overcoder.net

Python-сообщество

[RSS Feed]

  • Начало
  • » Python для новичков
  • » code review Ребят подскажите как ускорить выполнение программы

#1 Янв. 6, 2020 20:30:12

code review Ребят подскажите как ускорить выполнение программы

Всем доброго времени суток
Написал программку, но меня не устраивает время выполнения, хотелось бы побыстрее.
Полагаю есть несколько способов как ускорить:
— Запускать в какой-то среде разработки или в консоли(я запускал в текстовом редакторе Sublime)
— Подключить какую-то библиотеку, чтоб распаралелить выполнение(в процессе выполнения, у меня, было задействовано одно ядро, процессор грузился в среднем на 17-18 %)
— Улучшить код программы
— Возможно что-то еще, о чем даже не знаю что такое может быть)

Читайте также:
Какие программы открывают max

import os import pandas as pd #digit from str def extract_deg(input_str): if input_str is None or input_str == »: return 0 out_number = » f = 0 for ele in input_str: if ele.isdigit() or ele == ‘-‘: out_number += ele elif ele == ‘,’: out_number += ‘.’ f = 1 if f == 1: out_number = (float(out_number)) else: out_number = (int(out_number)) return (out_number) frame = pd.DataFrame() af = os.listdir(path=».») nf = af[10:-5] for i in nf: frame = frame.append(pd.read_csv(i), ignore_index=True) frame.to_csv(«datatest.csv», encoding=’utf-8′, sep=’t’, index=False) frame[‘minmax’] = frame[‘MAX’] — frame[‘MIN’] #массивы переменных dlst = [‘dvar1’, ‘dvar2’, . , ‘dvar11’] slst = [‘svar1’, ‘svar2’, . , ‘svar20’] elst = [‘evar1’, ‘evar2’, . , ‘evar44’] blst = [‘year’, ‘mounth’, ‘day’, ‘hh’, ‘mm’] sls = [] for i in slst: exec(i + ‘ = []’) exec(‘sls.append(‘+i+’)’) els = [] for i in elst: exec(i + ‘ = []’) exec(‘els.append(‘+i+’)’) bls = [] for i in blst: exec(i + ‘ = []’) exec(‘bls.append(‘+i+’)’) print(len(frame)) for i in range(len(frame)): year.append(int(str(frame[‘DATE’][i])[:4])) mounth.append(int(str(frame[‘DATE’][i])[4:6])) day.append(int(str(frame[‘DATE’][i])[6:8])) hh.append(int(str(frame[‘TIME’][i])[:2])) mm.append(int(str(frame[‘TIME’][i])[2:4])) time = [year[i], mounth[i], day[i], hh[i], mm[i], 0] print(i, end=’ ‘) #def1, def2 собирают текстовые данные, из которых, #при помощи extract_deg вытаскиваются числовые значения for p in range(len(dlst)-1): l = (def1(dlst[p], time)) sls[p*2].append(l[0]) sls[(p*2)+1].append(l[1]) for p in range(len(dlst)): l = (def2(dlst[p], time)) els[p*4].append(l[0]) els[(p*4)+1].append(l[1]) els[(p*4)+2].append(l[2]) els[(p*4)+3].append(l[3]) alllst = sls + els + bls salllst = slst + elst + blst for i in range(len(alllst)): frame[salllst[i]] = pd.Series(alllst[i]) frame.to_csv(«data.csv», encoding=’utf-8′, sep=’t’, index=False)

Пока вы это читаете, сделаю чтоб результат выводился не в конце выполнения программы, а к примеру каждые 10000 строк датафрейма)

Источник: python.su

Параллелизм, конкурентность и AsyncIO в Python — на примере

Конкурентность и параллелизм — похожие термины, но это не одно и то же.

Конкуренция — это возможность одновременного выполнения нескольких задач на ЦП. Задачи могут запускаться, выполняться и завершаться в перекрывающиеся периоды времени. В случае одного процессора несколько задач выполняются с помощью переключения контекстов, когда состояние процесса сохраняется, чтобы его можно было вызвать и выполнить позже.

Параллелизм — это возможность одновременного выполнения нескольких задач на нескольких ядрах процессора.

Хотя они могут увеличить скорость работы вашего приложения, параллелизм и параллельность не следует использовать повсеместно. Вариант использования зависит от того, является ли задача процессорозависимой или IO-зависимой.

Задачи, которые ограничиваются центральным процессором, привязаны к процессору. Например, математические вычисления привязаны к процессору, поскольку вычислительная мощность увеличивается с ростом числа процессоров компьютера. Параллелизм предназначен для задач, ограниченных центральным процессором. Теоретически, если задача разделена на n подзадач, каждая из этих n задач может выполняться параллельно, чтобы эффективно сократить время до 1/n исходной непараллельной задачи. Параллельность предпочтительна для задач, связанных с IO, поскольку вы можете заниматься чем-то другим, пока происходит выборка ресурсов IO.

Лучшим примером задач с привязкой к процессору является наука о данных. Специалисты по изучению данных работают с огромными массивами данных. Для предварительной обработки данных они могут разделить их на несколько пакетов и запускать их параллельно, эффективно сокращая общее время обработки. Увеличение количества ядер приводит к ускорению обработки данных.

Web scraping является IO-bound. Поскольку эта задача мало влияет на процессор, так как большая часть времени тратится на чтение из сети и запись в сеть. Другие распространенные IO-bound задачи включают вызовы баз данных, чтение и запись файлов на диск. Веб-приложения, такие как Django и Flask, являются IO-bound приложениями.

Если вам интересно узнать больше о различиях между потоками, мультипроцессингом и async в Python, ознакомьтесь со статьей Speeding Up Python with Concurrency, Parallelism, and asyncio.

Сценарий

Давайте рассмотрим, как ускорить выполнение следующих задач:

# tasks.py import os from multiprocessing import current_process from threading import current_thread import requests def make_request(num): # io-bound pid = os.getpid() thread_name = current_thread().name process_name = current_process().name print(f» — — «) requests.get(«https://httpbin.org/ip») async def make_request_async(num, client): # io-bound pid = os.getpid() thread_name = current_thread().name process_name = current_process().name print(f» — — «) await client.get(«https://httpbin.org/ip») def get_prime_numbers(num): # cpu-bound pid = os.getpid() thread_name = current_thread().name process_name = current_process().name print(f» — — «) numbers = [] prime = [True for i in range(num + 1)] p = 2 while p * p

Все примеры кода в этом руководстве можно найти в репозитории parallel-concurrent-examples-python.

  • make_request делает HTTP запрос на https://httpbin.org/ip X количество раз.
  • make_request_async делает тот же самый HTTP запрос асинхронно с HTTPX.
  • get_prime_numbers вычисляет простые числа методом Решето Эратосфена от двух до заданного предела.

Для ускорения выполнения вышеуказанных задач мы будем использовать следующие библиотеки из стандартной библиотеки:

  • поточность для одновременного выполнения задач
  • multiprocessing для параллельного выполнения задач
  • concurrent.futures для одновременного и параллельного выполнения задач из одного интерфейса
  • asyncio для параллельного выполнения задач с корутинами, управляемыми интерпретатором Python

IO-bound Operation

Опять же, связанные с IO задачи тратят больше времени на IO, чем на CPU.

Поскольку веб-скрейпинг связан с IO, мы должны использовать потоки для ускорения обработки, поскольку получение HTML (IO) происходит медленнее, чем его разбор (CPU).

Сценарий: Как ускорить скрипт веб-скрейпинга и краулинга на базе Python?

Пример синхронизации

Начнем с эталона.

# io-bound_sync.py import time from tasks import make_request def main(): for num in range(1, 101): make_request(num) if __name__ == «__main__»: start_time = time.perf_counter() main() end_time = time.perf_counter() print(f»Elapsed run time: seconds.»)

Читайте также:
Почему не сохраняются программы на компьютер

Здесь мы сделали 100 HTTP-запросов с помощью функции make_request . Поскольку запросы происходят синхронно, каждая задача выполняется последовательно.

Elapsed run time: 15.710984757 seconds.

Итак, это примерно 0,16 секунды на один запрос.

Пример потоковой обработки

# io-bound_concurrent_1.py import threading import time from tasks import make_request def main(): tasks = [] for num in range(1, 101): tasks.append(threading.Thread(target=make_request, args=(num,))) tasks[-1].start() for task in tasks: task.join() if __name__ == «__main__»: start_time = time.perf_counter() main() end_time = time.perf_counter() print(f»Elapsed run time: seconds.»)

Здесь одна и та же функция make_request вызывается 100 раз. На этот раз для создания потока для каждого запроса используется библиотека threading .

Elapsed run time: 1.020112515 seconds.

Общее время уменьшается с ~16с до ~1с.

Поскольку мы используем отдельные потоки для каждого запроса, вы можете задаться вопросом, почему все это не заняло ~0,16 с для завершения. Это дополнительное время — накладные расходы на управление потоками. Глобальная блокировка интерпретатора (GIL) в Python гарантирует, что только один поток одновременно использует байткод Python.

concurrent.futures Пример

# io-bound_concurrent_2.py import time from concurrent.futures import ThreadPoolExecutor, wait from tasks import make_request def main(): futures = [] with ThreadPoolExecutor() as executor: for num in range(1, 101): futures.append(executor.submit(make_request, num)) wait(futures) if __name__ == «__main__»: start_time = time.perf_counter() main() end_time = time.perf_counter() print(f»Elapsed run time: seconds.»)

Здесь мы использовали concurrent.futures.ThreadPoolExecutor для достижения многопоточности. После создания всех фьючерсов/обещаний мы использовали wait , чтобы дождаться их завершения.

Elapsed run time: 1.340592231 seconds

concurrent.futures.ThreadPoolExecutor фактически является абстракцией вокруг библиотеки multithreading , что упрощает ее использование. В предыдущем примере мы назначили каждый запрос на поток, и в общей сложности было использовано 100 потоков. Но в ThreadPoolExecutor по умолчанию количество рабочих потоков равно min(32, os.cpu_count() + 4) . ThreadPoolExecutor существует для того, чтобы облегчить процесс достижения многопоточности. Если вы хотите получить больший контроль над многопоточностью, используйте вместо этого библиотеку multithreading .

Пример AsyncIO

# io-bound_concurrent_3.py import asyncio import time import httpx from tasks import make_request_async async def main(): async with httpx.AsyncClient() as client: return await asyncio.gather( *[make_request_async(num, client) for num in range(1, 101)] ) if __name__ == «__main__»: start_time = time.perf_counter() loop = asyncio.get_event_loop() loop.run_until_complete(main()) end_time = time.perf_counter() elapsed_time = end_time — start_time print(f»Elapsed run time: seconds»)

httpx используется здесь, поскольку requests не поддерживает асинхронные операции.

Здесь мы использовали asyncio для достижения параллелизма.

Elapsed run time: 0.553961068 seconds

asyncio быстрее, чем другие методы, потому что threading использует потоки ОС (операционной системы). Таким образом, потоки управляются ОС, и переключение потоков происходит с ее помощью. asyncio использует корутины, которые определяются интерпретатором Python. С помощью coroutines программа решает, когда оптимально переключать задачи. За это отвечает even_loop в asyncio.

Операция с ограничением вычислительной мощности

Сценарий: Как ускорить простой скрипт обработки данных?

Пример синхронизации

Опять же, давайте начнем с эталона.

# cpu-bound_sync.py import time from tasks import get_prime_numbers def main(): for num in range(1000, 16000): get_prime_numbers(num) if __name__ == «__main__»: start_time = time.perf_counter() main() end_time = time.perf_counter() print(f»Elapsed run time: seconds.»)

Здесь мы выполнили функцию get_prime_numbers для чисел от 1000 до 16000.

Elapsed run time: 17.863046316 seconds.

Пример многопроцессорной обработки

# cpu-bound_parallel_1.py import time from multiprocessing import Pool, cpu_count from tasks import get_prime_numbers def main(): with Pool(cpu_count() — 1) as p: p.starmap(get_prime_numbers, zip(range(1000, 16000))) p.close() p.join() if __name__ == «__main__»: start_time = time.perf_counter() main() end_time = time.perf_counter() print(f»Elapsed run time: seconds.»)

Здесь мы использовали multiprocessing для вычисления простых чисел.

Elapsed run time: 2.9848740599999997 seconds.

concurrent.futures Пример

# cpu-bound_parallel_2.py import time from concurrent.futures import ProcessPoolExecutor, wait from multiprocessing import cpu_count from tasks import get_prime_numbers def main(): futures = [] with ProcessPoolExecutor(cpu_count() — 1) as executor: for num in range(1000, 16000): futures.append(executor.submit(get_prime_numbers, num)) wait(futures) if __name__ == «__main__»: start_time = time.perf_counter() main() end_time = time.perf_counter() print(f»Elapsed run time: seconds.»)

Здесь мы добились многопроцессорности с помощью concurrent.futures.ProcessPoolExecutor . Как только задания добавляются во фьючерсы, wait(futures) ожидает их завершения.

Elapsed run time: 4.452427557 seconds.

concurrent.futures.ProcessPoolExecutor является оберткой вокруг multiprocessing.Pool . Она имеет те же ограничения, что и ThreadPoolExecutor . Если вам нужен больший контроль над многопроцессорностью, используйте multiprocessing.Pool . concurrent.futures предоставляет абстракцию как над мультипроцессингом, так и над потоками, что позволяет легко переключаться между ними.

Заключение

Стоит отметить, что использование многопроцессорной обработки для выполнения функции make_request будет намного медленнее, чем потоковый вариант, так как процессы должны будут ждать ввода-вывода. Однако многопроцессорный подход будет быстрее, чем синхронный.

Аналогично, использование параллелизма для задач, привязанных к процессору, не стоит усилий по сравнению с параллелизмом.

При этом использование параллелизма или параллельности для выполнения скриптов усложняет работу. Ваш код будет труднее читать, тестировать и отлаживать, поэтому используйте их только в случае крайней необходимости для долго выполняющихся сценариев.

concurrent.futures — это то, с чего я обычно начинаю, поскольку-

  1. Легко переключаться туда-сюда между параллелизмом и параллельностью
  2. Зависимым библиотекам не нужно поддерживать asyncio ( requests против httpx )
  3. Чище и легче читать по сравнению с другими подходами

Возьмите код из репозитория parallel-concurrent-examples-python на GitHub.

Источник: django.fun

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru