Я использую unordered_map как разреженный 3D-массив (128 x 128 x 128) для вставки значений в сетку, если ячейка сетки по-прежнему свободна.
До сих пор я всегда проверял с помощью find(), если ячейка свободна, и если она есть, то я добавил элемент, используя insert() или emplace(). Теперь я обнаружил, что могу использовать возвращаемое значение insert и emplace, чтобы проверить, был ли добавлен элемент или уже был элемент с тем же ключом внутри карты. Я думал, что это может повысить производительность, поскольку я могу полностью удалить использование find.
Как оказалось, вместо того, чтобы улучшать производительность, вставляя без поиска, производительность действительно уменьшалась, и я не уверен, почему.
Я уменьшил свое приложение до этого примера, где точки генерируются случайным образом, а затем вставляются в сетку.
#include <unordered_map>
#include <random>
#include <chrono>
#include <iostream>
#include <math.h>
#include <algorithm>
#include <string>
using std::cout;
using std::endl;
using std::chrono::high_resolution_clock;
using std::chrono::milliseconds;
using std::chrono::duration_cast;
using std::unordered_map;
int num_elements = 5'000'000;
void findThenInsert(){
cout << endl << "find and emplace" << endl;
auto start = high_resolution_clock::now();
std::mt19937 gen(123);
std::uniform_real_distribution<> dis(0, 128);
unordered_map<int, int> grid;
int count = 0;
for(int i = 0; i < num_elements; i++){
float x = dis(gen);
float y = dis(gen);
float z = (cos(x*0.1) * sin(x*0.1) + 1.0) * 64.0;
int index = int(x) + int(y) * 128 + int(z) * 128 * 128;
auto it = grid.find(index);
if(it == grid.end()){
grid.emplace(index, count);
count++;
}
}
cout << "elements: " << count << endl;
cout << "load factor: " << grid.load_factor() << endl;
auto end = high_resolution_clock::now();
long long duration = duration_cast<milliseconds>(end - start).count();
float seconds = duration / 1000.0f;
cout << seconds << "s" << endl;
}
void insertThenCheckForSuccess(){
cout << endl << "emplace and check success" << endl;
auto start = high_resolution_clock::now();
std::mt19937 gen(123);
std::uniform_real_distribution<> dis(0, 128);
unordered_map<int, int> grid;
int count = 0;
for(int i = 0; i < num_elements; i++){
float x = dis(gen);
float y = dis(gen);
float z = (cos(x*0.1) * sin(x*0.1) + 1.0) * 64.0;
int index = int(x) + int(y) * 128 + int(z) * 128 * 128;
auto it = grid.emplace(index, count);
if(it.second){
count++;
}
}
cout << "elements: " << count << endl;
cout << "load factor: " << grid.load_factor() << endl;
auto end = high_resolution_clock::now();
long long duration = duration_cast<milliseconds>(end - start).count();
float seconds = duration / 1000.0f;
cout << seconds << "s" << endl;
}
int main(){
findThenInsert();
insertThenCheckForSuccess();
}
В обоих случаях размер карты составляет 82901, поэтому я предполагаю, что результат будет точно таким же.
find and emplace: 0.937s emplace then check: 1.268s