Производительность вложенного цикла в numba

По соображениям производительности я начал использовать Numba помимо NumPy. Мой алгоритм Numba работает, но я чувствую, что он должен быть быстрее. Есть один момент, который замедляет его. Вот фрагмент кода:

@nb.njit def rfunc1(ws, a, l): gn = a**l for x1 in range(gn): for x2 in range(gn): for x3 in range(gn): y = 0.0 for i in range(1, l): if numpy.all(ws[x1][0:i] == ws[x2][0:i]) and numpy.all(ws[x1][i:l] == ws[x3][i:l]): y += 1 if numpy.all(ws[x1][0:i] == ws[x2][0:i]) and numpy.all(ws[x1][i:l] == ws[x3][i:l]): y += 1 

По-моему, команда if замедляет ее. Есть ли способ лучше? (То, что я пытаюсь достичь здесь, связано с предыдущей проблемой: Count для одиночных кроссоверов ) ws – массив NumPy размера (gn, l) содержащий 0 и 1

2 Solutions collect form web for “Производительность вложенного цикла в numba”

Учитывая логику того, чтобы все элементы были равны, вы можете воспользоваться тем фактом, что, если они не равны, вы можете выполнить короткое замыкание (т.е. прекратить сравнение) вычисления. Я немного изменил вашу оригинальную функцию, чтобы (1) вы не повторяли одно и то же сравнение дважды, и (2) суммировали y по всем вложенным циклам, чтобы можно было сравнить результат:

 @nb.njit def rfunc1(ws, a, l): gn = a**l ysum = 0 for x1 in range(gn): for x2 in range(gn): for x3 in range(gn): y = 0.0 for i in range(1, l): if np.all(ws[x1][0:i] == ws[x2][0:i]) and np.all(ws[x1][i:l] == ws[x3][i:l]): y += 1 ysum += 1 return ysum @nb.njit def rfunc2(ws, a, l): gn = a**l ysum = 0 for x1 in range(gn): for x2 in range(gn): for x3 in range(gn): y = 0.0 for i in range(1, l): incr_y = True for j in range(i): if ws[x1,j] != ws[x2,j]: incr_y = False break if incr_y is True: for j in range(i,l): if ws[x1,j] != ws[x3,j]: incr_y = False break if incr_y is True: y += 1 ysum += 1 return ysum 

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

Теперь для некоторых таймингов:

 l = 7 a = 2 gn = a**l ws = np.random.randint(0,2,size=(gn,l)) In [23]: %timeit rfunc1(ws, a , l) 1 loop, best of 3: 2.11 s per loop %timeit rfunc2(ws, a , l) 1 loop, best of 3: 39.9 ms per loop In [27]: rfunc1(ws, a , l) Out[27]: 131919 In [30]: rfunc2(ws, a , l) Out[30]: 131919 

Это дает вам 50-кратное ускорение.

Вместо того, чтобы просто «иметь чувство», где ваше узкое место, почему бы не профилировать ваш код и не найти именно там?

Первой целью профилирования является проверка репрезентативной системы для определения того, что происходит медленно (или с использованием слишком большого количества ОЗУ или чрезмерного количества операций ввода-вывода или сетевого ввода-вывода).

Профилирование обычно добавляет накладные расходы (от 10x до 100x замедление может быть типичным), и вы по-прежнему хотите, чтобы ваш код использовался как можно ближе к реальной ситуации. Извлеките тестовый кейс и изолируйте часть системы, которую необходимо протестировать. Предпочтительно, это будет написано уже в своем собственном наборе модулей.

Основные методы включают в %timeit магию %timeit в IPython, time.time(), и time.time(), timing decorator (см. Пример ниже). Вы можете использовать эти методы для понимания поведения операторов и функций.

Затем у вас есть cProfile который даст вам представление на высоком уровне проблемы, чтобы вы могли обратить ваше внимание на критические функции.

Затем просмотрите line_profiler, который будет профилировать выбранные вами функции по очереди. Результат будет включать в себя подсчет количества раз, когда вызывается каждая строка, и процент времени, затраченного на каждую строку. Это именно то, что вам нужно, чтобы понять, что работает медленно и почему.

perf stat помогает понять количество инструкций, которые в конечном итоге выполняются на процессоре, и насколько эффективно используются кеши процессора. Это позволяет осуществлять расширенную настройку матричных операций.

heapy может отслеживать все объекты внутри памяти Python. Это отлично подходит для поиска странных утечек памяти. Если вы работаете с многолетними системами, то dowser заинтересовал dowser : он позволяет вам интроспективно dowser живые объекты в длительном процессе через интерфейс веб-браузера.

Чтобы помочь вам понять, почему ваше использование ОЗУ очень велико, проверьте memory_profiler. Это особенно полезно для отслеживания использования ОЗУ с течением времени на маркированной диаграмме, поэтому вы можете объяснить коллегам (или вам самим), почему некоторые функции используют больше ОЗУ, чем ожидалось.

Пример: определение декоратора для автоматизации измерений времени

 from functools import wraps def timefn(fn): @wraps(fn) def measure_time(*args, **kwargs): t1 = time.time() result = fn(*args, **kwargs) t2 = time.time() print ("@timefn:" + fn.func_name + " took " + str(t2 - t1) + " seconds") return result return measure_time @timefn def your_func(var1, var2): ... 

Для получения дополнительной информации я предлагаю прочитать высокопроизводительный Python (Micha Gorelick, Ian Ozsvald), из которого было получено исходное.

  • Цветовая гамма - близко, но недостаточно близко
  • Как читать CSV без первого столбца
  • Изменение размера и растяжения массива NumPy
  • numpy cov (ковариация), что именно он вычисляет?
  • Интеграция не увенчалась успехом в Python QuTiP
  • Смущение при изменении формы изображения
  • Как найти максимальное значение в столбце массива numpy?
  • Есть ли более быстрый способ добавить два массива 2-х numpy
  •  
    Interesting Posts for Van-Lav

    Как правильно писать пути к файлу в Python

    Эффективно найти, содержит ли строка группу символов (например, подстроку, но игнорируя порядок)?

    Перемещение электронной почты в GMail с помощью Python и imaplib

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

    Строки объединены в Python

    Шифрование и расшифровка с использованием PyCrypto AES 256

    Как сделать чат, как пользовательский интерфейс, используя Python Urwid?

    Данные о точках метки метки объекта Seaborn FacetGrid PointPlot

    несколько json словарей python

    Создание кортежей всех возможных комбинаций элементов из двух списков без дублирования элементов внутри кортежей

    urllib2 не возвращает полную веб-страницу

    Выбор подходящего способа использования Neo4j в Python

    Ошибка упаковки Kivy с библиотекой numpy для Android с использованием buildozer

    matplotlib: пользовательская проекция для полусферы / клина

    Гуникорн с флягой с использованием неправильного Python

    Python - лучший язык программирования в мире.