«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > В поисках производительности, часть II: Perl против Python

В поисках производительности, часть II: Perl против Python

Опубликовано 1 августа 2024 г.
Просматривать:458

The Quest for Performance Part II : Perl vs Python


Запустив пример игрушечной производительности, мы теперь немного отвлечемся и сравним производительность с
несколько реализаций Python. Сначала давайте настроим сцену для вычислений и предоставим командную строку
возможности сценария Python.

import argparse
import time
import math
import numpy as np
import os
from numba import njit
from joblib import Parallel, delayed

parser = argparse.ArgumentParser()
parser.add_argument("--workers", type=int, default=8)
parser.add_argument("--arraysize", type=int, default=100_000_000)
args = parser.parse_args()
# Set the number of threads to 1 for different libraries
print("=" * 80)
print(
    f"\nStarting the benchmark for {args.arraysize} elements "
    f"using {args.workers} threads/workers\n"
)

# Generate the data structures for the benchmark
array0 = [np.random.rand() for _ in range(args.arraysize)]
array1 = array0.copy()
array2 = array0.copy()
array_in_np = np.array(array1)
array_in_np_copy = array_in_np.copy()

А вот и наши участники:

  • Базовый Python
  for i in range(len(array0)):
    array0[i] = math.cos(math.sin(math.sqrt(array0[i])))
  • Numpy (Однопоточный)
np.sqrt(array_in_np, out=array_in_np)
np.sin(array_in_np, out=array_in_np)
np.cos(array_in_np, out=array_in_np)
  • Joblib (обратите внимание, что этот пример не является настоящим примером на месте, но мне не удалось запустить его с использованием аргументов out)
def compute_inplace_with_joblib(chunk):
    return np.cos(np.sin(np.sqrt(chunk))) #parallel function for joblib

chunks = np.array_split(array1, args.workers)  # Split the array into chunks
numresults = Parallel(n_jobs=args.workers)(
        delayed(compute_inplace_with_joblib)(chunk) for chunk in chunks
    )# Process each chunk in a separate thread
array1 = np.concatenate(numresults)  # Concatenate the results
  • Нумба
@njit
def compute_inplace_with_numba(array):
    np.sqrt(array,array)
    np.sin(array,array)
    np.cos(array,array)
    ## njit will compile this function to machine code
compute_inplace_with_numba(array_in_np_copy)

И вот результаты хронометража:

In place in (  base Python): 11.42 seconds
In place in (Python Joblib): 4.59 seconds
In place in ( Python Numba): 2.62 seconds
In place in ( Python Numpy): 0.92 seconds

Нумба на удивление медленнее!? Может ли это быть связано с накладными расходами на компиляцию, как указал mohawk2 в обмене сообщениями IRC по этой проблеме?
Чтобы проверить это, мы должны вызвать Compute_inplace_with_numba один раз перед выполнением теста. Это показывает, что Numba теперь быстрее, чем Numpy.

In place in (  base Python): 11.89 seconds
In place in (Python Joblib): 4.42 seconds
In place in ( Python Numpy): 0.93 seconds
In place in ( Python Numba): 0.49 seconds

Наконец, я решил взять для катания базу R в том же примере:

n



что дало следующий результат синхронизации:

Time in base R: 1.30 seconds

По сравнению с результатами Perl в этом примере мы отмечаем следующее:

  • Операции на месте в базовом Python были примерно на 3,5 медленнее, чем в Perl
  • Однопоточный PDL и numpy дали почти одинаковые результаты, за ними следовал базовый R
  • Неспособность учесть накладные расходы на компиляцию Numba создает ложное впечатление, что он медленнее, чем Numpy. С учетом затрат на компиляцию Numba в 2 раза быстрее, чем Numpy
  • Распараллеливание с помощью Joblib улучшило базовый Python, но все равно уступало однопоточной реализации Perl
  • Многопоточный PDL (и OpenMP) сокрушил (не сломал!) все остальные реализации на всех языках). Надеюсь, этот пост дает пищу для размышлений язык, который будет использоваться для вашей следующей операции с интенсивными данными/вычислениями. В следующей части этой серии будет рассмотрен тот же пример с использованием массивов в C. Эта последняя часть (надеюсь) даст некоторое представление о влиянии локальности памяти и накладных расходах, возникающих при использовании динамически типизированных языков.
Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/chrisarg/the-quest-for- Performance-part-ii-perl-vs-python-5gdg?1. В случае нарушения прав обращайтесь по адресу [email protected]. удалить его
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3