#python #numpy #runtime #nested-for-loop
#питон #тупица #время выполнения #вложенный для цикла
Вопрос:
В настоящее время я работаю над проектом, который требует от меня запуска полной базы кода python. В исследовательских целях мне нужно запустить код как можно быстрее. Тем не менее, я довольно новичок в программировании и понятия не имею, как сократить время выполнения. Поэтому я надеюсь, что кто-нибудь сможет мне в этом помочь. Буду признателен за любой совет. Вот часть моей базы кода, в которой использовалось много вложенных циклов for, поэтому это может значительно увеличить время выполнения.
def a_j(r, a, A): # the Claussius-Mossotti factor, determined by a symmetric (3 × 3) matrix such that (A_i)^T = A_i alph = np.array([[0,0,0],[0,0,0],[0,0,0]],complex) for i in range(3): for j in range(3): alph[i,j] = (r * a * A[i,j]) return alph def W_ext(x, k, rho, alpha, A): # particle–particle interaction term n = x.shape[0] # the number of x vextors result = np.zeros([3*n,3*n],complex) u = np.zeros((n, 3)) # u = x - x' for i in range(n): for j in range(n): if i != j: u[i] = x[i] - x[j] block_result = a_j(rho[i], alpha, A) * G((u[i]), k) * a_j(rho[j], alpha, A) for m in range(3): for l in range(3): result[3*i m, 3*j l] = block_result[m,l] return result.imag def A_ext(rho, a, A): # single-particle term n = rho.shape[0] result = np.zeros([3*n,3*n],complex) for i in range(n): for j in range(n): if i == j: block_result = a_j(rho[i], a, A).imag for m in range(3): for l in range(3): result[3*i m, 3*j l] = block_result[m,l] return result # (3 x 3) matrix def P_ext(e, A, W, omega): eT = np.matrix.getH(e) mm1 = np.matmul(A, e) mm2 = np.matmul(W, e) extinction = (np.dot(eT, mm1) np.dot(eT, mm2)) * (omega/2.0) return extinction #ABSORPTION def W_abs(x, k, rho, alpha, A, chi): # particle–particle interaction term n = x.shape[0] result = np.zeros([3*n,3*n],complex) u = np.zeros((n, 3)) for i in range(n): for j in range(n): if i != j: u[i] = x[i] - x[j] block_result = np.matrix.getH(a_j(rho[i], alpha, A)) * (1.0 / np.conjugate(chi)).imag * a_j(rho[i], alpha, A) * G((u[i]), k) * a_j(rho[j], alpha, A) for m in range(3): for l in range(3): result[3*i m, 3*j l] = block_result[m,l] return 2.0 * result.real # (3 x 3) matrix def A_abs(rho, a, A, chi): # single-particle term n = rho.shape[0] result = np.zeros([3*n,3*n],complex) for i in range(n): for j in range(n): if i == j: block_result = np.matrix.getH(a_j(rho[i], a, A)) * (1.0 / np.conjugate(chi)).imag * a_j(rho[i], a, A) for m in range(3): for l in range(3): result[3*i m, 3*j l] = block_result[m,l] return result # (3 x 3) matrix
Комментарии:
1. что это за соглашение об именовании О. О.
2. Один пример: если у вас есть вложенный цикл над i и j, с «если(i==j)» в теле, просто отбросьте внутренний цикл и используйте «i» там, где в данный момент отображается «j». Аналогично в некоторых других def.
3. Что такое
a_j
? вложенныеfor
циклы всегда будут увеличивать время выполнения. Первые 2 цикла сами по себе учитываютO(n^2)
временную сложность. Добавьте к этому любую стоимость звонкаa_j
.4. Python — это не тот путь, по которому нужно идти, если вы хотите действительно хорошей производительности, особенно для циклов, которые имеют много накладных расходов по сравнению с чем-то, созданным с помощью собственного кода. Для этого вам нужно будет использовать библиотеки Python, которые являются скомпилированными двоичными файлами, или создать свою собственную библиотеку, или использовать Cython или что-то подобное, чтобы объединить высокопроизводительный код C с гибкостью Python.
5. Я не
numpy
эксперт, но я думаю, что большая часть смысла использованияnp.array
, как вы пытаетесь сделать, заключается в том, чтобы взять типы операций, которые вы выполняете вfor
циклах Python, и поместить их вnumpy
вызовы, которые выполняются как скомпилированный C, а не в интерпретаторе Python. Я предлагаю провести некоторое время с документами numpy, чтобы посмотреть, есть ли функции, которые могли бы выполнять эквивалент того, что вы сейчас делаете в своем собственном коде.