Я работаю над небольшим кусочком кода, который итеративно переносит плотность от одного временного шага к другому, пока не будет достигнуто время назначения
Код, над которым я работаю, имеет следующую форму:
пинг-понг между двумя буферами сейчас и далее
Мой вопрос: есть ли общий шаблон, как ускорить такой кусок кода?
Дополнительный вопрос: могу ли я реализовать это лучше / лучше, используя алгоритмы stl?
std::vector<double> ping;
std::vector<double> pong;
ping.reserve(1000000);
pong.reserve(1000000);std::vector* now= &ping;
std::vector* next = &pong;
Initialize(now); // Fill first timestep
for(size_t t = 0; t < 1000; t++) // timesteps
{
size_t M = now->size();
size_t N = calcNewRefinement(t, now);
next->resize(N);
for(size_t i = 0; i < N; i++) // all elements
{
for(size_t j = 0; j < now->size(); j++)
{
if (j > 0 && j < N)
(*next)[i] += ExpensiveFunction((*now)[j-1], (*now)[j], (*now)[j+1], (*next)[i])
else if (j == 0)
(*next)[i] += ExpensiveFunction2((*now)[j], (*now)[j+1], (*next)[i])
else if (j == M-1)
(*next)[i] += ExpensiveFunction3((*now)[j-1], (*now)[j], (*next)[i])
}
}
vector<double> *intermediate = now;
now = next;
next = intermediate;
}
Общий совет по оптимизации должен сделать профилирование первый. Я предполагаю, что вы уже сделали это и обнаружили, что ваши «операции копирования и доступа» (как описано в вопросе) должны быть оптимизированы.
В этом случае позвольте мне отметить, что имя ExpensiveFunction
вводит в заблуждение, потому что это не может быть дорогостоящим, когда несколько операций копирования и доступа так важны в вашем коде.
«Общая схема» для оптимизации: посмотрите на свой внутренний цикл, и попробуйте удалить ненужные операции.
В вашем случае у вас есть следующее:
for (...; j < now->size(); ...)
— попробуйте заменить now->size()
от M
— есть хороший шанс, что ваш компилятор уже сделал это, но вы никогда не знаете …if (j > 0 && < j < N)
— вы можете полностью удалить эти проверки, если разделите свой цикл на 3 части (первая итерация; средние итерации; последняя итерация)now[j-1], now[j], now[j+1]
— некоторые реализации c ++ настаивают на проверке границ массива для каждого доступа (это не требуется для c ++); если у вас так, попробуйте отключить проверку или замените std::vector
от std::array
или (если это не помогает) массивом в стиле Cnext[i] = ...
— как указано вышеДругих решений пока нет …