Я пытаюсь переписать код MATLAB ниже в Python и обнаружил, что мой код Python (2,7 сек) медленнее, чем MATLAB (1,2 секунды). Я пробовал много разных способов, включая модуль numba, но пока не повезло. Как я могу сделать код Python быстрее?
szA=[1024,1280]; HfszA=[512,640];
[aPx,aPy]=meshgrid(-HfszA(2):HfszA(2)-1,-HfszA(1):HfszA(1)-1);
img=randi(255,1024,1280);
fx=rand(); fy=rand();
tic
for i=1:20
F=abs(sum(sum(img.*exp(-1i*2*pi*(fx*aPx+fy*aPy)))));
end
toc
import numpy as np
import time
szA=[1024,1280]; HfszA=[512,640]
aPx,aPy=np.meshgrid(np.arange(-HfszA[1],HfszA[1]),np.arange(-HfszA[0],HfszA[0]))
img=np.array(np.random.randint(256,size=(1024,1280)))
fx=np.random.rand()
fy=np.random.rand()
start = time.time()
for i in range(20):
F=abs(np.sum(img*np.exp(-1j*2*np.pi*(fx*aPx+fy*aPy))))
end = time.time()
print("Elapsed (after compilation) = %s" % (end - start))
print(F)
Всегда отправляйте то, что вы пробовали. Что касается вашей версии Numba, я думаю, вы сделали что-то, что приводит к плохой производительности.
пример
import numpy as np
import numba as nb
import time
@nb.njit(fastmath=True)
def your_function(fx,fy,aPx,aPy,img):
pi=np.pi
sum=0.
for i in range(aPx.shape[0]):
for j in range(aPx.shape[1]):
sum+=img[i,j]*np.exp(-1j*2*pi*(fx*aPx[i,j]+fy*aPy[i,j]))
return np.abs(sum)
@nb.njit(fastmath=True,parallel=True)
def your_function_p(fx,fy,aPx,aPy,img):
pi=np.pi
sum=0.
for i in nb.prange(aPx.shape[0]):
for j in range(aPx.shape[1]):
sum+=img[i,j]*np.exp(-1j*2*pi*(fx*aPx[i,j]+fy*aPy[i,j]))
return np.abs(sum)
#The function gets compiled at the first call
#you may also use cache=True, which only works in single threaded code
F=your_function(fx,fy,aPx,aPy,img)
start = time.time()
for i in range(20):
F=your_function(fx,fy,aPx,aPy,img)
end = time.time()
print("Elapsed (after compilation) = %s" % (end - start))
print(F)
F=your_function_p(fx,fy,aPx,aPy,img)
start = time.time()
for i in range(20):
F=your_function_p(fx,fy,aPx,aPy,img)
end = time.time()
print("Elapsed (after compilation) = %s" % (end - start))
print(F)
Сроки (4C/8T)
your_version: 2.45s
Numba single threaded: 0.17s
Numba parallel: 0.07s
Я считаю, что вы даже можете попробовать более простую проблему
MATLAB
function test
szA=[1024,1280]; HfszA=[512,640];
[aPx,aPy]=meshgrid(-HfszA(2):HfszA(2)-1,-HfszA(1):HfszA(1)-1);
fx=1.0; fy=2.0;
tic
for i=1:2000
F=sum(sum(fx*aPx+fy*aPy));
end
toc
disp(F)
выходы
Истекшее время - 9.566274 секунды.
-1966080
питон
import numpy as np
import time
szA=[1024,1280]; HfszA=[512,640]
aPx,aPy=np.meshgrid(np.arange(-HfszA[1],HfszA[1]),np.arange(-HfszA[0],HfszA[0]))
fx=1.0
fy=2.0
start = time.time()
for i in range(2000):
F = np.sum(np.sum(fx*aPx+fy*aPy, axis=0))
end = time.time()
print("Elapsed (after compilation) = %s" % (end - start))
print(F)
выходы
Истекший (после компиляции) = 33.3840000629
-1966080.0
Я считаю, что разница между ними в два раза:
Причина, по которой я пришел к такому выводу, - это посмотреть на использование ЦП на моем Core i3 с четырьмя ядрами (вы можете проверить количество ядер на вашем процессоре), при этом скрипт python составляет 30%, а Matlab - 100%.
Что касается инструкции AVX, установите только то, что я когда-то сравнивал работу Matmul MATLAB с Eigen one (http://eigen.tuxfamily.org/index.php?title=Main_Page), и для соответствия производительности мне пришлось скомпилировать Eigen с [ CN02] и -axAVX.
Чтобы, наконец, ответить на ваш вопрос, я не думаю, что вы можете сделать код Python быстрее, если не сможете скомпилировать базовую библиотеку numpy с директивой openmp, AVX.
Вот учебник https://docs.scipy.org/doc/scipy/reference/building/linux.html
Удачи, дайте нам знать, как все прошло.