Так что я действительно не был уверен в результатах, поэтому я провел несколько тестов.
Мой тест должен был иметь список длиной 10000 и иметь окно размером 1000, скользящее по нему. Затем в каждой итерации просто суммируйте все элементы окна, а затем суммируйте все результаты всех итераций.
Таковы результаты:
run_sliced: 296.210 ms/it (Iterations: 7)
run_memoryview: 409.670 ms/it (Iterations: 5)
run_shift: 296.495 ms/it (Iterations: 7)
run_cpp: 3.066 ms/it (Iterations: 653)
run_rust: 1.132 ms/it (Iterations: 1768)
Самая странная часть этого теста - то, что memoryview
был самым медленным.
Не совсем уверен, что с этим делать.
Python:
import time
import array
# Our external c++ and rust functions
import ext_cpp
import ext_rust
# List of size 10000.
# Our moving window is size 1000. That means we need to slice 9000 times.
# We simply take the sum of all numbers in the window,
# and then again the sum of all windows.
# Just to prevent any optimizations from happening.
listSize = 10000
windowSize = 1000
a = list(range(listSize))
numWindows = listSize - windowSize + 1
def time_it(name, func):
t0 = time.perf_counter()
iterations = 0
while True:
assert(func(a) == 45000499500)
iterations += 1
t1 = time.perf_counter()
if t1 - t0 > 2:
break
per_iteration = 1000.0*(t1-t0)/iterations
print("{:<15}".format(name+":")
+ "{:>10}".format(format(per_iteration, '.3f')) + " ms/it"
+ " (Iterations: " + str(iterations) + ")")
def run_sliced(a):
r = 0
for i in range(numWindows):
window = a[i:i+windowSize]
for el in window:
r += el
return r
def run_memoryview(a):
r = 0
a_raw = array.array('l', a)
a = memoryview(a_raw)
for i in range(numWindows):
window = a[i:i+windowSize]
for el in window:
r += el
return r
def run_shift(a):
r = 0
window = a[:windowSize]
for el in window:
r += el
for i in range(1, numWindows):
window = window[1:]
window.append(a[i + windowSize - 1])
for el in window:
r += el
return r
def run_cpp(a):
return ext_cpp.run(a, numWindows, windowSize)
def run_rust(a):
return ext_rust.run(a, numWindows, windowSize)
time_it('run_sliced', run_sliced)
time_it('run_memoryview', run_memoryview)
time_it('run_shift', run_shift)
time_it('run_cpp', run_cpp)
time_it('run_rust', run_rust)
C ++ (pybind11):
long run(std::vector<long> a, long windowSize, long numWindows){
long r = 0;
for(long i = 0; i < numWindows; i++){
const long* window = &a[i];
for(long j = 0; j < windowSize; j++){
r += window[j];
}
}
return r;
}
Ржавчина (PyO3):
fn run(_py: Python, a: Vec<u64>, num_windows: usize, window_size: usize)
-> PyResult<u64>
{
let mut r = 0;
for i in 0..num_windows {
let window = &a[i..i+window_size];
for el in window {
r += el;
}
}
Ok(r)
}