Необъяснимая производительность на технологии big.LITTLE (на Android) - PullRequest
0 голосов
/ 05 сентября 2018

Я прошу прощения за длинный вопрос, но я пытаюсь измерить производительность различных методов индексации на различных платформах, одной из которых является Дерево 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 , за исключением случаев, когда размер данных равен слишком низко.

Чтобы диагностировать, что может быть не так, я прошел следующие шаги:

  1. Убедитесь, что поток работает на максимальной скорости, используя следующий код:

    void set_thread_priority() {
        nice(-20);
        int policy = 0;
        struct sched_param param;
        pthread_getschedparam(pthread_self(), &policy, &param);
        param.sched_priority = sched_get_priority_max(policy);
        pthread_setschedparam(pthread_self(), policy, &param);
    }
    

Я мог видеть, что приятное значение отражается в процессе, и поток в большинстве случаев работает на 100% ЦП (это в основном однопоточный алгоритм).

  1. Установите привязку ЦП, используя следующий код:

    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 в обоих случаях.

  1. Убедитесь, что для моего набора данных достаточно свободного ОЗУ

  2. Чтобы избежать возможности извлечения шага 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();

Какие-нибудь указатели относительно того, что я мог бы сделать дальше? Или есть объяснение этому с точки зрения платформы?

...