2016-04-16 6 views
3

Я пытаюсь избежать использования циклов для выполнения моих вычислений. Но я не знаю, как это сделать. У меня есть матрица w с формой (40,100). Каждая строка удерживает позицию до волны в t раз. Например, первая строка w[0] является начальным условием (также w[1] по причинам, которые я покажу).Оптимизация вложенного цикла

Для вычисления следующих элементов строки, которые я использую, для каждого t и x на диапазон формы:

w[t+1,x] = a * w[t,x] + b * (w[t,x-1] + w[t,x+1]) - w[t-1,x] 

Где a и b некоторые константы на основе решения уравнения (это на самом деле не имеет значения), a = 2(1-r) , b=r, r=(c*(dt/dx))**2. Где c - это скорость волны, а dt, dx относятся к приращению на x и t направлении.

Есть ли способ, чтобы избежать цикла, как:

for t in range(1,nt-1): 
    for x in range(1,nx-1): 
     w[t+1,x] = a * w[t,x] + b * (w[t,x-1] + w[t,x+1]) - w[t-1,x] 

nt и nx являются формой w матрицы.

+1

Я рекомендую вам взглянуть на [это учебник] (https: // GitHub.com/barbagroup/CFDPython) для реализации дифференциальных уравнений с частными производными (в данном случае Navier-Stokes) в Python. –

+0

Большое спасибо @RolandSmith. – Lin

ответ

5

Я предполагаю, что вы заранее задаете w[:,0] и w[:-1] (некоторым константам?), Потому что я не вижу его в цикле. Если да, то вы можете устранить for x цикл векторизации эту часть кода:

for t in range(1,nt-1): 
    w[t+1,1:-1] = a*w[t,1:-1] + b*(w[t,:-2] + w[t,2:]) - w[t-1,1:-1] 
0

Не совсем. Если вы хотите что-то сделать для каждого элемента в своей матрице (что вы делаете), вам придется каким-то образом воздействовать на каждый элемент (наиболее очевидным способом является цикл for. Менее очевидные методы будут выполнять то же или хуже).

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

Как правило, с такими матричными проблемами, когда вы смотрите на соседние элементы, хорошее решение использует какое-то динамическое программирование или memoization (экономя вашу работу, поэтому вам не нужно часто повторять вычисления). Например, предположим, что для каждого элемента вы хотели бы усреднить его и все, что вокруг него (как размываются изображения). Каждый пиксель имеет 8 соседей, поэтому средним будет сумма/9. Ну, допустим, вы сохраняете суммы столбцов (за исключением NW + W + SW, N + me + S, NE + E + SE). Хорошо, когда вы переходите к следующему справа, просто суммируйте значения предыдущего предыдущего столбца, предыдущего предыдущего столбца и значений нового столбца (новые справа). Вы только что заменили добавление 9 чисел с добавлением 5. В операциях, которые сложнее, чем добавление, сокращение от 9 до 5 может означать огромное увеличение производительности.

Я посмотрел, что вы должны сделать, и я не мог придумать, как сделать что-то вроде описанного мной. Но посмотрите, можете ли вы придумать что-то подобное.

Кроме того, помните, что умножение намного дороже, чем добавление. Итак, если у вас есть цикл, где, например, вам нужно было умножить некоторое число на переменную цикла, вместо того, чтобы делать 1x, 2x, 3x, ..., вы можете сделать (значение в последний раз + x).

+1

Одна из особенностей 'numpy' заключается в том, что ее операторы и функции действуют по элементу массива. Это упрощает запись таких задач. Под капотом это реализуется как цикл *, но в C вместо Python *, что делает его намного быстрее. –

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