Я сравнил версию numexpr
с простой реализацией Numpy следующим образом:
#!/usr/bin/env python3
import numpy as np
import numexpr as ne
# Ensure repeatable, deterministic randomness!
np.random.seed(42)
# Generate test arrays
N = 1000000
X = np.random.rand(N)
Y = np.random.rand(N)
# Define centre and radius
cx = cy = r = 0.5
def method1(X,Y,cx,cy,r):
"""Straight Numpy determination of points in circle"""
d = (X-cx)**2 + (Y-cy)**2
res = d < r**2
return res
def method2(X,Y,cx,cy,r):
"""Numexpr determination of points in circle"""
res = ne.evaluate('((X-cx)**2 + (Y-cy)**2)<r**2')
return res
def method3(data,a,b,r):
"""List based determination of points in circle, with pre-filtering using a square"""
in_square_points = [(x,y) for (x,y) in data if a-r < x < a+r and b-r < y < b+r]
in_circle_points = [(x,y) for (x,y) in in_square_points if (x-a)**2 + (y-b)**2 < r**2]
return in_circle_points
# Timing
%timeit method1(X,Y,cx,cy,r)
%timeit method2(X,Y,cx,cy,r)
# Massage input data (before timing) to match agorithm
data=[(x,y) for x,y in zip(X,Y)]
%timeit method3(data,cx,cy,r)
Затем я рассчитал ее в I Python следующим образом:
%timeit method1(X,Y,cx,cy,r)
6.68 ms ± 246 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit method2(X,Y,cx,cy,r)
743 µs ± 17.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit method3(data,cx,cy,r)
1.11 s ± 9.81 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Таким образом, версия numexpr
вышла в 9 раз быстрее. Поскольку точки l ie находятся в диапазоне [0..1], алгоритм эффективно вычисляет pi
, и оба метода получаются одинаковыми:
method1(X,Y,cx,cy,r).sum()
784973
method2(X,Y,cx,cy,r).sum()
784973
len(method3(data,cx,cy,r))
784973
4 * 784973 / N
3.139
Примечание : Я должен отметить, что numexpr
автоматически выполняет многопоточность вашего кода на нескольких ядрах процессора. Если вам хочется поэкспериментировать с количеством потоков, вы можете изменить его динамически перед вызовом method2()
или даже внутри него:
# Split calculations across 6 threads
ne.set_num_threads(6)
Любой другой, желающий проверить скорость их метод может использовать мой код в качестве основы для тестирования.