Форум сайта python.su
0
Здравствуйте! Может быть глупый вопрос, но никак не разберусь..
Как написать функцию, которая применяется к массиву numpy не поэлементно, а к подмассивам.
Т.е. есть такой цикл, который работает медленно:
for ii in xrange(len(ccc)):
for j in xrange(len(ccc[ii,:,:])):
if ccc[ii,j,0]>0 or ccc[ii,j,1]>0 or ccc[ii,j,2]>0:
ccc[ii,j,0]=255
ccc[ii,j,1]=255
ccc[ii,j,2]=255
Отредактировано iezhov (Дек. 14, 2012 05:22:11)
Офлайн
43
import numpy as np def ff1(ccc): for ii in xrange(len(ccc)): for j in xrange(len(ccc[ii,:,:])): if ccc[ii,j,0]>0 or ccc[ii,j,1]>0 or ccc[ii,j,2]>0: ccc[ii,j,0]=255 ccc[ii,j,1]=255 ccc[ii,j,2]=255 def ff2(ccc): for row in ccc: for pix in row: if pix[0]|pix[1]|pix[2]: pix[0]=pix[1]=pix[2]=255 ccc1 = np.ndarray([10,20,3],np.ubyte) ccc2 = ccc1.copy() %%timeit ff1(ccc1) 1000 loops, best of 3: 1.65 ms per loop %%timeit ff2(ccc2) 10000 loops, best of 3: 137 us per loop
Отредактировано sergeek (Дек. 14, 2012 11:39:05)
Офлайн
0
Спасибо за ответ!
Офлайн
16
Вариант sergeek, безусловно, понятнее и правильнее, но существенное падение скорости даёт всего одна строчка:
import numpy as np def ff1(ccc): for ii in xrange(len(ccc)): for j in xrange(len(ccc[ii,:,:])): if ccc[ii, j, 0] or ccc[ii, j, 1] or ccc[ii, j, 2]: # убрали сравнение с нулём ccc[ii, j, 0] = 255 ccc[ii, j, 1] = 255 ccc[ii, j, 2] = 255 def ff2(ccc): for row in ccc: for pix in row: if pix[0] | pix[1] | pix[2]: pix[0] = pix[1] = pix[2] = 255 ccc1 = np.ndarray([10, 20, 3], np.ubyte) ccc2 = ccc1.copy() %%timeit ff1(ccc1) 1000 loops, best of 3: 378 us per loop %%timeit ff2(ccc2) 1000 loops, best of 3: 507 us per loop
Отредактировано GaiveR (Дек. 15, 2012 22:05:38)
Офлайн
0
Я думал медленно из-за xrange, а оно вон как.. Спасибо! В любом случае, с такой скоростью уже вполне замечательно. 
Офлайн
43
странно, когда я делал тесты ленивое сравнение было медленее, а теперь наоборот, причем повторил много раз. Можно конечно предположить что тогда ненули расположились ближе к старшим позициям. Но меня смущает вот это
%%timeit 1|1|1 100000000 loops, best of 3: 14.9 ns per loop %%timeit 0 or 0 or 1 10000000 loops, best of 3: 37.2 ns per loop %%timeit 0 or 1 or 1 10000000 loops, best of 3: 33.5 ns per loop %%timeit 1 or 1 or 1 10000000 loops, best of 3: 24.1 ns per loop
Офлайн
16
Действительно, для обычных чисел оптимальнее использовать битовые операции.
Но у ТС там np.ubyte:
a = np.ubyte(1) b = np.ubyte(1) c = np.ubyte(1) %%timeit a | b | c 1000000 loops, best of 3: 640 ns per loop %%timeit a or b or c 10000000 loops, best of 3: 90 ns per loop b = np.ubyte(0) %%timeit a or b or c 10000000 loops, best of 3: 166 ns per loop c = np.ubyte(0) %%timeit a or b or c 10000000 loops, best of 3: 168 ns per loop
Офлайн