Почему мой пространственный хэш такой медленный?

Почему мой пространственный хеш такой медленный? Я работаю над кодом, который использует гидродинамику гладких частиц для моделирования движения оползней. В гидродинамике гладких частиц каждая частица воздействует на частицы, которые находятся на расстоянии 3 «длин сглаживания». Я пытаюсь реализовать пространственную хэш-функцию для быстрого поиска соседних частиц.

Для моей реализации я использовал тип данных set из stl. На каждом временном шаге частицы хэшируются в свое ведро, используя функцию ниже. «Ведро» — это вектор наборов, с одним набором для каждой ячейки сетки (пространственная область ограничена). Каждая частица идентифицируется целым числом.

Для поиска коллизий используется функция ниже, названная «getSurroundingParticles», которая принимает целое число (соответствующее частице) и возвращает набор, содержащий все ячейки сетки, которые находятся в пределах 3 опорных длин частицы.

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

//put each particle into its bucket(s)
void hashParticles()
{
int grid_cell0;

cellsWithParticles.clear();

for(int i = 0; i<N; i++)
{
//determine the four grid cells that surround the particle, as well as the grid cell that the particle occupies
//using the hash function int grid_cell = ( floor(x/cell size) ) + ( floor(y/cell size) )*width
grid_cell0 = ( floor( (Xnew[i])/cell_spacing) ) + ( floor(Ynew[i]/cell_spacing) )*cell_width;

//keep track of cells with particles, cellsWithParticles is an unordered set so duplicates will automatically be deleted
cellsWithParticles.insert(grid_cell0);//since each of the hash buckets is an unordered set any duplicates will be deleted
buckets[grid_cell0].insert(i);

}
}

set<int> getSurroundingParticles(int particleOfInterest)
{
set<int> surroundingParticles;
int numSurrounding;
float divisor = (support_length/cell_spacing);
numSurrounding = ceil( divisor );
int grid_cell;

for(int i = -numSurrounding; i <= numSurrounding; i++)
{
for(int j = -numSurrounding; j <= numSurrounding; j++)
{
grid_cell = (int)( floor( ((Xnew[particleOfInterest])+j*cell_spacing)/cell_spacing) ) + ( floor((Ynew[particleOfInterest]+i*cell_spacing)/cell_spacing) )*cell_width;
surroundingParticles.insert(buckets[grid_cell].begin(),buckets[grid_cell].end());
}
}
return surroundingParticles;
}

Код, который просматривает вызовы getSurroundingParticles:

set<int> nearbyParticles;
//for each bucket with particles in it
for ( int i = 0; i < N; i++ )
{
nearbyParticles = getSurroundingParticles(i);
//for each particle in the bucket

for ( std::set<int>::iterator ipoint = nearbyParticles.begin(); ipoint != nearbyParticles.end(); ++ipoint )
{
//do stuff to check if the smaller subset of particles collide
}
}

Большое спасибо!

2

Решение

Ваша производительность съедается живым из-за огромного количества выделений кучи stl, вызванного многократным созданием и заполнением всех этих Наборов. Если вы профилировали код (скажем, с помощью быстрого и простого неинструментального инструмента, такого как Sleepy), я уверен, что вы найдете это именно так. Вы используете наборы, чтобы избежать добавления данной частицы в корзину более одного раза — я понял. Если предложение Дак не дает вам то, что вам нужно, я думаю, вы могли бы значительно улучшить производительность, используя предварительно распределенные массивы или векторы, и получить уникальность в этих контейнерах, добавив флаг «добавлено» к частице, которая устанавливается при добавлении элемента , Затем просто проверьте этот флаг перед добавлением и обязательно очистите флаги перед следующим циклом. (Если число частиц постоянное, вы можете сделать это чрезвычайно эффективно с помощью предварительно выделенного массива, предназначенного для хранения флагов, а затем установите значение 0 в конце кадра.)

Это основная идея. Если вы решите пойти по этому пути и застрять где-нибудь, я помогу вам проработать детали.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]