Я не уверен, сколько SIMD выиграет;Внутренний цикл довольно маленький и простой, поэтому я думаю (просто глядя), что вы, вероятно, больше связаны с памятью, чем все остальное.Имея это в виду, я бы попробовал переписать основную часть цикла, чтобы не касаться массива частиц больше, чем нужно:
const double temp_vX = particles[i].vX - boxes[boxnum].mX;
const double temp_vY = particles[i].vY - boxes[boxnum].mY;
if(boxes[boxnum].rotDir == 1)
{
nX = temp_vX*Wxx+temp_vY*Wxy;
nY = temp_vX*Wyx+temp_vY*Wyy;
}
else
{
//to make it randomly pick a rot. direction
nX = temp_vX*Wxx-temp_vY*Wxy;
nY = -temp_vX*Wyx+temp_vY*Wyy;
}
particles[i].vX = nX;
particles[i].vY = nY;
Это имеет небольшой потенциальный побочный эффект - не делать дополнительного сложения вend.
Другим потенциальным ускорением было бы использование __restrict
в массиве частиц, чтобы компилятор мог лучше оптимизировать записи по скоростям.Кроме того, если Wxx и т. Д. Являются глобальными переменными, им, возможно, придется каждый раз перезагружаться через цикл, а не сохранять их в регистрах;использование __restrict
также поможет в этом.
Поскольку вы обращаетесь к частицам по порядку, вы можете попробовать предварительную выборку (например, __builtin_prefetch
в GCC) на несколько частиц вперед, чтобы уменьшить потери в кэше.Предварительная выборка на полях немного сложнее, поскольку вы получаете к ним доступ в непредсказуемом порядке;Вы можете попробовать что-то вроде
int nextBoxnum = ((((int)(particles[i+1].sX+boxShiftX) /// etc...
// prefetch boxes[nextBoxnum]
Последнее, что я только что заметил - если box :: rotDir всегда +/- 1.0, тогда вы можете исключить сравнение и переход во внутреннем цикле, какэто:
const double rot = boxes[boxnum].rotDir; // always +/- 1.0
nX = particles[i].vX*Wxx + rot*particles[i].vY*Wxy;
nY = rot*particles[i].vX*Wyx + particles[i].vY*Wyy;
Естественно, обычные предостережения о профилировании до и после применения.Но я думаю, что все это может помочь, и может быть сделано независимо от того, переключаетесь ли вы на SIMD.