Подтвердить что ты не робот

Невозможно принудительно включить функцию С++ с помощью компилятора Intel

У меня есть функция, определенная как

inline void vec_add(__m512d &v3, const __m512d &v1, const __m512d &v2) {
    v3 = _mm512_add_pd(v1, v2);
}

(__m512d - это собственное сопоставление типа данных для регистров SIMD в архитектуре Intel MIC)

Поскольку эта функция довольно короткая и часто вызывается, я бы хотел, чтобы она была встроена при каждом вызове. Но компилятор Intel, похоже, неохотно встраивает эту функцию даже после использования опций -inline-forceinline и -O3. В нем сообщается, что "Forceinline not honored for call..." при компиляции. Поскольку я должен использовать некоторые специфичные для компилятора функции, например. тип __m512d, компилятор Intel - мой единственный вариант.

Дополнительная информация:

Структура файла довольно проста. Функция vec_add определяется в заголовочном файле mic.h, который включен в другой файл test.cc. Функция vec_add просто вызывается повторно в цикле, и в ней нет указателей на функции. A упрощенная версия кода в test.cc выглядит так:

for (int i = 0; i < LENGTH; i += 8) {
    // a, b, c are arrays of doubles, and each SIMD register can hold 8 doubles
    __mm512d va = _mm512_load_pd(a + i); // load SIMD register from memory
    __mm512d vb = _mm512_load_pd(b + i); // ditto
    __mm512d vc;
    vec_add(vc, va, vb); // store SIMD register to memory
    _mm512_store_pd(c + i, vc);
}

Я пробовал всевозможные подсказки, такие как __attribute__((always_inline)), __forceinline и параметр компилятора -inline-forceinline, ни один из которых не работал.

Полный код

Я собрал весь соответствующий код в упрощенной форме. Вы можете попробовать, если у вас есть компилятор Intel. Используйте опцию -Winline для просмотра встроенных отчетов и -inline-forceinline для принудительной вставки.

#include <stdio.h>
#include <stdlib.h>
#include <immintrin.h>

#define LEN (1<<20)

__attribute((target(mic)))
inline void vec_add(__m512d &v3, const __m512d &v1, const __m512d &v2) {
    v3 = _mm512_add_pd(v1, v2);
}

int main() {
    #pragma offload target(mic)
    {
        double *a = (double*)_mm_malloc(LEN*sizeof(double), 64);
        double *b = (double*)_mm_malloc(LEN*sizeof(double), 64);
        double *c = (double*)_mm_malloc(LEN*sizeof(double), 64);

        for (int i = 0; i < LEN; i++) {
            a[i] = (double)rand()/RAND_MAX;
            b[i] = (double)rand()/RAND_MAX;
        }

        for (int i = 0; i < LEN; i += 8) {
            __m512d va = _mm512_load_pd(a + i);
            __m512d vb = _mm512_load_pd(b + i);
            __m512d vc;
            vec_add(vc, va, vb);
            _mm512_store_pd(c + i, vc);
        }

        _mm_free(a);
        _mm_free(b);
        _mm_free(c);
    }
}

Конфигурация

  • Компилятор: компилятор Intel (ICC) 14.0.2
  • Параметры компиляции: -O3 -inline-forceinline -Winline

У вас есть идея, почему эта функция не может быть встроена? И как я могу получить его inlined в конце концов (я не хочу обращаться к макросам)?

4b9b3361

Ответ 1

По какой-то причине Intel Compiler не выполняет функции функций в выгруженном коде (я не так хорошо знаком с этой концепцией, поэтому не знаю, какая техническая причина для этого). См. effective-use-of-the-intel-compilers-offload-features для получения дополнительной информации (просто найдите "встроенный" ).

Цитата из связанной статьи:

Функция Встраивание в конструкцию выгрузки

Иногда для обеспечения максимальной производительности сгенерированный код. Функции, вызываемые непосредственно внутри разгрузки #pragma не встроены компилятором, даже если они отмечены как встроенные. к обеспечить оптимальную производительность кода в регионах разгрузки, либо вручную встроенные функции, или поместить всю конструкцию разгрузки в ее собственную функция.

...

Одним из решений является функция inline вручную, как показано в функции v2.

Другое решение - переместить конструкцию разгрузки в ее собственную как показано в функции v3.

Если я правильно понимаю это, лучше всего сделать для вас петли в отдельную функцию, которая также отмечена __attribute ((target (mic))).