"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > La búsqueda del rendimiento Parte II: Perl vs Python

La búsqueda del rendimiento Parte II: Perl vs Python

Publicado el 2024-08-01
Navegar:194

The Quest for Performance Part II : Perl vs Python


Después de ejecutar un ejemplo de rendimiento de un juguete, ahora haremos una pequeña digresión y contrastaremos el rendimiento con
algunas implementaciones de Python. Primero, configuremos el escenario para los cálculos y proporcionemos la línea de comando
capacidades al script 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()

Y aquí están nuestros concursantes:

  • Python base
  for i in range(len(array0)):
    array0[i] = math.cos(math.sin(math.sqrt(array0[i])))
  • Numpy (un solo hilo)
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 (tenga en cuenta que este ejemplo no es un ejemplo real, pero no he podido ejecutarlo usando los argumentos 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
  • Numba
@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)

Y aquí están los resultados del tiempo:

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

¿¡El numba es sorprendentemente más lento!? ¿Podría deberse a los gastos generales de compilación como lo señaló mohawk2 en un intercambio de IRC sobre este tema?
Para probar esto, debemos llamar a Compute_inplace_with_numba una vez antes de ejecutar el punto de referencia. Al hacerlo, se muestra que Numba ahora es más rápido que 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

Finalmente, decidí usar la base R para montar en el mismo ejemplo:

n



que arrojó el siguiente resultado de tiempo:

Time in base R: 1.30 seconds

En comparación con los resultados de Perl, observamos lo siguiente sobre este ejemplo:

  • Las operaciones in situ en Python base fueron ~ 3,5 más lentas que Perl
  • PDL de un solo subproceso y numpy dieron resultados casi idénticos, seguidos de cerca por la base R
  • No tener en cuenta la sobrecarga de compilación de Numba produce la falsa impresión de que es más lento que Numpy. Al tener en cuenta los gastos generales de compilación, Numba es x2 más rápido que Numpy
  • La paralelización con Joblib mejoró con respecto a Python base, pero aún era inferior a la implementación de Perl de un solo subproceso
  • PDL multiproceso (y OpenMP) aplastaron (¡no bloquearon!) todas las demás implementaciones en todos los idiomas). Ojalá esta publicación proporciona algo de reflexión el idioma a utilizar para su próxima operación intensiva de datos/cómputo. La siguiente parte de esta serie analizará el mismo ejemplo usando matrices en C. Esta última entrega (con suerte) proporcionará algunas ideas sobre el impacto de la localidad de memoria y la sobrecarga que se genera al usar lenguajes tipados dinámicamente.
Declaración de liberación Este artículo se reproduce en: https://dev.to/chrisarg/the-quest-for-performance-part-ii-perl-vs-python-5gdg?1 Si hay alguna infracción, comuníquese con [email protected] para borrarlo
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3