У меня есть функция, определенная как
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 в конце концов (я не хочу обращаться к макросам)?