Во время оптимизации моего подключения четырех игровых движков я достиг точки, когда только дальнейшие улучшения могут быть минимальными, поскольку большая часть времени процессора используется инструкцией TableEntry te = mTable[idx + i]
в следующем примере кода. *
TableEntry getTableEntry(unsigned __int64 lock)
{
int idx = (lock & 0xFFFFF) * BUCKETSIZE;
for (int i = 0; i < BUCKETSIZE; i++)
{
TableEntry te = mTable[idx + i]; // bottleneck, about 35% of CPU usage
if (te.height == NOTSET || lock == te.lock)
return te;
}
return TableEntry();
}
Хеш-таблица mTable
определяется как std::vector<TableEntry>
и имеет около 4,2 мил. записи (около 64 МБ). Я попытался заменить vector
, выделив таблицу с new
без улучшения скорости.
Я подозреваю, что случайный доступ к памяти (из-за функции Zobrist Hashing ) может быть дорогим, но неужели так много? У вас есть предложения по улучшению функции?
Спасибо!
Редактировать: BUCKETSIZE
имеет значение 4. Он используется как стратегия столкновения . Размер одного TableEntry составляет 16 байт, структура выглядит следующим образом:
struct TableEntry
{ // Old New
unsigned __int64 lock; // 8 8
enum { VALID, UBOUND, LBOUND }flag; // 4 4
short score; // 4 2
char move; // 4 1
char height; // 4 1
// -------
// 24 16 Bytes
TableEntry() : lock(0LL), flag(VALID), score(0), move(0), height(-127) {}
};
Краткое описание: Первоначально для функции требовалось 39 секунд. После внесения изменений, предложенных jdehaan, функции теперь нужно 33 секунды (программа останавливается через 100 секунд). Лучше, но я думаю, что Конрад Рудольф прав, и главная причина, почему он так медленен, - это кеш пропускает.