2015-07-24 1 views
2

У меня есть петли в python, которые повторяются почти 2,5 миллиона раз, и для получения результата требуется столько времени. В JS я могу сделать это примерно за 1 секунду, но Python делает это через 6 секунд на моем компьютере. В этом случае я должен использовать Python. Вот код:Ускорение циклов с методами списка в Python

  for i in xrange(k,p,2): 
       arx = process[i] 
       ary = process[i+1] 
       for j in xrange(7,-1,-1): 
        nx = arx + dirf[j] 
        ny = ary + dirg[j] 
        ind = ny*w+nx 
        if data[ind] == e[j]:  
         process[c]=nx 
         c=c+1 
         process[c]=ny 
         c=c+1 
         matrix[ind]=1 

Вот некоторые списки из кода: process = [None] * (11000*4) это детали будут заменены с целыми после его присвоения.

dirf = [-1,0,1,-1,1,-1,0,1] 
dirg = [1,1,1,0,0,-1,-1,-1] 
e = [9, 8, 7, 6, 4, 3, 2, 1] 

Список данных состоит из информации 'r' из пикселей изображения rgba. data = imgobj.getdata(0)

Как я могу увеличить это. Что я делаю не так? Есть ли какие-либо другие подходы к циклам? Благодарю.

+0

Требуется 34,9 * миллисекунды * для итерации 2,5 миллиона раз на моей машине (это медленно, но это не 6 секунд медленно). – jfs

+0

это быстро, но только при использовании без заданий ниже. Я должен работать с ними. – malisit

+0

Вы пробовали numba http://numba.pydata.org/, чтобы ускорить ваш питон? – fgoettel

ответ

-3

Вот несколько советов для улучшения кода:

Этот внутренний xrange используется много: то, что если вы сделали, что обычный список и просто сделал что-то вроде этого:

inner = range(7,-1,-1) # make the actual list 
for(a,b,c): #first for 
    #stuff 
    for i in inner # reference an actual list and not the generator 

Evidence :

n = range(7,-1,-1) 
def one(): 
    z = 0 
    for k in xrange(100): 
     for i in n: 
      z+=1 

def two(): 
    z = 0 
    for k in xrange(100): 
     for i in xrange(7,-1,-1): 
      z+=1 

if __name__ == '__main__': 
    import timeit 
    print("one:") 
    print(timeit.timeit("one()",number=1000000 ,setup="from __main__ import one")) 
    print("two:") 
    print(timeit.timeit("two()",number=1000000 ,setup="from __main__ import two")) 

"result" 
one: 
37.798637867 
two: 
63.5098838806 

Если код, который я написал сопоставимый, казалось бы указать, что ссылки на внутренний список и не создает действительно ускоряет его. [edit] Ссылка на локальную переменную быстрее, чем доступ к глобальной. , так что если это правильно, поместите определение списка как можно ближе к циклу, не генерируя его каждый раз.

Вы также меняете процесс дважды. Если это не нужно, просто выберите один.

Как вы упомянули в комментариях, вы говорите, что работаете с изображениями. Я не уверен, что следующее релевантно, но, возможно, вы можете использовать openCV, который имеет API Python для кода C. Это может ускорить его. Как отмечали другие: numpy и ваши собственные расширения cython значительно ускорят это.

+2

Ваш набор таймингов для присваиваний не показывает ускорение десятой доли секунды - это 'e-08' в конце означает, что разница фактически примерно * наносекунда *. Ваши тайминги за то, что вы не вызываете 'xrange' каждый раз вокруг цикла, дают ускорение (63,5 - 37,8)/100 000 секунд, что составляет [менее 26 микросекунд] (http://www.wolframalpha.com/input/?i=% 2863,5 + - + 37,8% 29% 2F1000000 + секунд). Даже в критической внутренней петле эти типы микрооптимизации, вероятно, окажут совершенно незначительное влияние на общее время работы. – lvc

+0

Да, я согласен, я забыл прочитать экспонента, удалит этот раздел. – NevDev

+1

Бит, который вы оставили, почти так же плох, поскольку: а) вы не усреднили время по количеству проходов, а b) изменение, которое вы тестируете, влияет на весь внешний цикл один раз. Даже если внешняя петля OPs повторяет несколько больше, чем ваш пример, вы предоставили доказательства того, что они могут сэкономить, самое большее, за несколько миллисекунд за шесть секунд. – lvc

Смежные вопросы