Рассмотрим следующий пример делать в InPlace добавьте на memoryview Cython:векторизации зацикливание на массив из Cython
#cython: boundscheck=False, wraparound=False, initializedcheck=False, nonecheck=False, cdivision=True
from libc.stdlib cimport malloc, free
from libc.stdio cimport printf
cimport numpy as np
import numpy as np
cdef extern from "time.h":
int clock()
cdef void inplace_add(double[::1] a, double[::1] b):
cdef int i
for i in range(a.shape[0]):
a[i] += b[i]
cdef void inplace_addlocal(double[::1] a, double[::1] b):
cdef int i, n = a.shape[0]
for i in range(n):
a[i] += b[i]
def main(int N):
cdef:
int rep = 1000000, i
double* pa = <double*>malloc(N * sizeof(double))
double* pb = <double*>malloc(N * sizeof(double))
double[::1] a = <double[:N]>pa
double[::1] b = <double[:N]>pb
int start
start = clock()
for i in range(N):
a[i] = b[i] = 1./(1 + i)
for i in range(rep):
inplace_add(a, b)
printf("loop %i\n", clock() - start)
print(np.asarray(a)[:4])
start = clock()
for i in range(N):
a[i] = b[i] = 1./(1 + i)
for i in range(rep):
inplace_addlocal(a, b)
printf("loop_local %i\n", clock() - start)
print(np.asarray(a)[:4])
С этими директивами Cython, казалось бы, эквивалентный inplace_add
и inplace_addlocal
как компилировать плотных петель C , Но для N=128
(приблизительный размер, который я ожидаю) inplace_addlocal
в два раза (!) Быстрее, чем inplace_add
, после компиляции с gcc -Ofast
(и прямое написание функции C, принимающей (int, double *, double *), является более или менее быстрым как addlocal
, с или без #openmp simd
). Пройдя -fopt-info
до gcc
, показано, что inplace_addlocal
получает векторный рисунок, но не inplace_add
.
Это проблема с кодом C, который генерирует Cython (т. Е. Gcc действительно не может вывести любые гарантии, необходимые для векторизации кода) или с gcc (т. Е. Некоторая оптимизация отсутствует) или что-то еще?
Спасибо.
(кросс-размещены на Cython пользователей)
Хороший улов. Любое объявление 'i' как' size_t' или литье 'a.shape [0]' to 'int' в вызове диапазона позволяет векторизовать. – antony