2015-10-31 3 views
2

Я новичок в python и пытаюсь узнать больше о том, как это работает, последовательно оптимизируя куски наивного кода, которые я уже написал.советы по производительности python - цикл, включающий сравнения

Следующая функция включает цикл, который выполняет операции над элементами списка списка поплавков только тогда, когда значения структуры данных удовлетворяют некоторому условию. Мне было интересно, может ли кто-нибудь прокомментировать (1) способы повышения производительности этого цикла и (2) общие характеристики типа цикла, который я описываю, что делает его более или менее подходящим для разных подходов к его улучшению. Ниже я включил минимальную версию цикла, с которым я работаю.

Некоторые заметки о переменных используется ниже:

#p is a small integer (say, p=10) 
#index1 is an integer between 0 and p 
#k is an integer between 0 and, say, kmax=100 
#mat1 is a list of list of floats whose size is [kmax,p], 
# with all values initialized to 0.0. 
# mat1 is changed by the loop below 
#mat2 is a list of list of floats whose size is [kmax,p] 
# with all values initialized to -2e10. 
# mat2 is changed by other parts of the program 

Кроме того, если это имеет значение, в моем коде все это часть класса, так что есть «я». операторов для переменных. Я прочитал, что локальные переменные лучше обрабатываются функциями python; как это переводится в конструкторы классов?

def greatFunction(index1,k):       
    index2 = index1 
    for j in range(p):       
     if (mat2[k][index2] > -1e10):   
      mat1[k][j] = mat1[k][j] + mat2[k][index1]*mat2[k][index2] 
     index2 = index2 - 1 
     if(index2 < 0): 
      index2 = index2 + p 

Из того, что я читал, я думал, что это будет главным кандидатом на замену списков списков с nparrays (в самом классе, а не превращение вещи в функции) и использование масок, чтобы заботиться о булевом условия. Тем не менее, версия numpy, которую я написал, оказалась медленнее, чем предыдущая версия python. Любая помощь, как ускорение кода, так и важнее, помогает мне понять, почему и как такие циклы могут быть заменены лучшей конструкцией, было бы высоко оценено. Спасибо!

+1

так как '(mat2 [k] [index2]> -1e10)' всегда False, mat1 = 0? –

+0

Извините, я должен был четко указать, что когда я сказал, что «mat2 изменен другими частями программы», эти изменения могут произойти между вызовами функции greatFunction. Таким образом, в общем случае нет (mat2 [k] [index2]> -1e10) не всегда False – David

ответ

0

Похоже index2 идет от index1 к 0 уменьшается с шагом 1, а затем циркулируют обратно p-1, а затем снова начинает уменьшаться. Это в основном modulo operation и, таким образом, может быть смоделировано с np.mod, чтобы дать нам index2 как индексы столбцов на каждой итерации. Затем мы индексируем строку k-thmat2 и используем индексы столбцов с предыдущего шага, чтобы получить все элементы, необходимые для нашей цели. Эти элементы сравниваются с порогом (-1e10 в нашем случае), что дает нам маску, которая используется для выбора элементов из этой строки и установки соответствующих в выходной массив mat1 после масштабирования с помощью mat2[k][index1].

Поскольку вы работаете с массивами NumPy, я предполагаю, что у вас уже есть mat1 и mat2 преобразованные в массивы NumPy с np.array().

Кроме того, как уже упоминалось в комментариях, если mat2 имеет все значения инициализируются в -2e10, то mat2[k][index2] > -1e10 никогда не будет true, так что в этом конкретном случае, mat1 сохранит свою zeros. Таким образом, чтобы в общем объяснить, как векторизовать такой случай, я принимаю mat2 вместо случайных чисел. Реализация будет выглядеть примерно так:

# Get column indices corresponding to index2 
col_idx = np.mod(np.arange(index1,index1-p,-1),p) 

# Get all mat2 values with those column indices at kth row 
mat2_val = mat2[k,col_idx] 

# Mask of valid elements 
mask = mat2_val > -1e10 

# Set valid ones in mat1 with valid ones from mat2 
# after scaling with mat2[k][index1] 
mat1[k][mask] = mat2[k][index1]*mat2_val[mask] 
+0

Спасибо, что нашли время, чтобы пройти через это, и для предоставления общей векторизации, поскольку, как упоминалось в ответ на комментарий другая часть программы может изменить mat2 вдали от ее начальных значений. – David

+0

Следуя за вопросами в конце моего сообщения, вы сказали бы, что такая реализация numpy - это самый быстрый или эффективный способ выполнения такого рода операций, или другие подходы к python будут лучше? – David

+0

@David Я бы подумал, что опубликованная версия была очень оптимизированной, учитывая, что она использует только функцию, а отдых - все нарезки и индексирование, поэтому должно быть довольно быстро. Единственным узким местом будет преобразование в массив NumPy из списка списков. – Divakar

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