Я прошу прощения за длинный вопрос, но я пытаюсь измерить производительность различных методов индексации на различных платформах, одной из которых является Дерево Adaptive Radix .
Я запустил тесты, в которых основные шаги выглядят так (c / c ++):
Step 1: Generate or load data (few million key-value pairs)
Step 2: Insert into index and measure time taken (insert_time)
Step 3: Retrieve from index and measure time taken (retrieve_time)
Я считаю, что всегда insert_time> retrieve_time на большинстве платформ, таких как настольные ПК Intel (i386 / amd64), iPad (Apple A9), Android (ARMv7) и Raspberry Pi 3 (ARMv8). Это логично, поскольку сложность вставки выше, чем сложность извлечения.
Но когда я запускаю шаги на платформах big.LITTLE, в частности Snapdragon 845 (Xiaomi POCO F1) и HiSilicon Kirin 659 (Honor 9 lite), я нахожу insert_time , за исключением случаев, когда размер данных равен слишком низко.
Чтобы диагностировать, что может быть не так, я прошел следующие шаги:
Убедитесь, что поток работает на максимальной скорости, используя следующий код:
void set_thread_priority() {
nice(-20);
int policy = 0;
struct sched_param param;
pthread_getschedparam(pthread_self(), &policy, ¶m);
param.sched_priority = sched_get_priority_max(policy);
pthread_setschedparam(pthread_self(), policy, ¶m);
}
Я мог видеть, что приятное значение отражается в процессе, и поток в большинстве случаев работает на 100% ЦП (это в основном однопоточный алгоритм).
Установите привязку ЦП, используя следующий код:
void set_affinity() {
cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(4, &mask);
CPU_SET(5, &mask);
CPU_SET(6, &mask);
CPU_SET(7, &mask);
sched_setaffinity(0, sizeof(mask), &mask);
}
Этот код также хорошо отражается на big.LITTLE, потому что, когда я устанавливаю CPU на 0, 1, 2, 3, код работает намного медленнее, чем когда я устанавливаю CPU на 4, 5, 6, 7. Даже тогда insert_time в обоих случаях.
Убедитесь, что для моего набора данных достаточно свободного ОЗУ
Чтобы избежать возможности извлечения шага 3 из виртуальной памяти, я добавил шаг 4, который просто повторяет шаг 3:
Step 4: Retrieve from index and measure time taken again (retrieve_time2)
К моему удивлению, retrieve_time2> retrieve_time> insert_time (от 2 до 3 секунд для 10 миллионов записей).
Что касается моего кода, код вставки выглядит следующим образом:
it1 = m.begin();
start = getTimeVal();
for (; it1 != m.end(); ++it1) {
art_insert(&at, (unsigned char*) it1->first.c_str(),
(int) it1->first.length() + 1, (void *) it1->second.c_str(),
(int) it1->second.length());
ctr++;
}
stop = getTimeVal();
и получить код выглядит так:
it1 = m.begin();
start = getTimeVal();
for (; it1 != m.end(); ++it1) {
int len;
char *value = (char *) art_search(&at,
(unsigned char*) it1->first.c_str(), (int) it1->first.length() + 1, &len);
ctr++;
}
stop = getTimeVal();
Какие-нибудь указатели относительно того, что я мог бы сделать дальше? Или есть объяснение этому с точки зрения платформы?