Шаблон C ++ медленнее, чем эквивалентный макрос C, почему? - PullRequest
0 голосов
/ 04 ноября 2019

В моей программе мне нужно быстро перебирать циклический список, реализованный в виде массива. Медленная часть цикла - это операция остатка (деление!), Которая требуется для того, чтобы индекс не выпал из дальнего конца массива. Таким образом, я ловко разделил цикл на три части, чтобы избежать оставшейся операции.

Чтобы уменьшить дублирование кода, я создал макрос C и шаблон C ++ для циклической конструкции, показанной ниже:

template <typename F>
static inline void
for_loop_pairs(int at, int loops, const F fun) {
    int right = MIN(loops, N - at - 1);
    int left = loops - right;
    while (right) {
        int next = at + 1;
        fun(at, next);
        at = next;
        next++;
        right--;
    }
    if (left) {
        fun(N - 1, 0);
        left--;
        at = 0;
        while (left) {
            int next = at + 1;
            fun(at, next);
            at = next;
            next++;
            left--;
        }
    }
}

#define FOR_LOOP_PAIRS(at, loops, fun)  \
    int right = MIN(loops, N - at - 1); \
    int left = loops - right;           \
    int k0 = at;                        \
    while (right) {                     \
        int k1 = k0 + 1;                \
        fun;                            \
        k0 = k1;                        \
        k1++;                           \
        right--;                        \
    }                                   \
    if (left) {                         \
        k0 = N - 1;                     \
        int k1 = 0;                     \
        fun;                            \
        left--;                         \
        k0 = 0;                         \
        while (left) {                  \
            k1 = k0 + 1;                \
            fun;                        \
            k0 = k1;                    \
            k1++;                       \
            left--;                     \
        }                               \
    }

N - это число элементов в массиве. Для вызова макроса и цикла for я использую:

FOR_LOOP_PAIRS(start, loops, {
    // Do stuff with k0 and k1, which are the indices.
});
for_loop_pairs(start, loops, [&](int k0, int k1) {
    // Do stuff with k0 and k1 which are the indices.
});

Версия с использованием шаблонов намного чище, но и на 5% медленнее, что недопустимо. Мой вопрос: что я делаю не так? Я ожидаю, что код шаблона выдаст точно такой же код, что и макрос.

Команда компиляции: g++ -Wall -Werror -fPIC -march=native -mtune=native -O3 -fomit-frame-pointer fname.cpp gcc версия 7.4.0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...