インテル® C++ コンパイラー 17.0 デベロッパー・ガイドおよびリファレンス

vector_variant

オリジナルの C/C++ スカラー関数に対応するベクトル関数を指定します。 このベクトル関数は、ベクトル・コンテキストで呼び出すことができます。

構文

Windows®:

__declspec(vector_variant(clauses))

Linux*:

__attribute__((vector_variant(clauses)))

引数

clauses

設定可能な値は以下のとおりです。

implements 節。implements (<function declarator>) [, <simd-clauses>]) 形式で指定します。function declarator はオリジナルのスカラー関数、simd-clausesvector 属性で許可されている 1 つ以上の節です。 simd-clauses はオプションです。

説明

この属性により、プログラマーはベクトル関数と対応するスカラー関数を表現できます。 コンパイラーは、ベクトル化されたループでスカラー関数の呼び出しをベクトル関数に置き換えます。

この属性に関する制限は以下のとおりです。

ユーザー定義のベクトル関数で mask 節を指定する場合、mask 引数は最後の引数にします。

以下に、ベクトル関数の例を示します。

#include<immintrin.h>
__declspec(noinline)
float MyAdd(float* a, int b) { return *a + b; }
__declspec(vector_variant(implements(MyAdd(float *a, int b)),       
                          linear(a), vectorlength(8),
                          nomask, processor(core_2nd_gen_avx)))
__m256 __regcall MyAddVec(float* v_a, __m128i v_b, __m128i v_b2) {
  __m256i t96 = _mm256_castsi128_si256(v_b);
  __m256i tmp = _mm256_insertf128_si256(t96, v_b2, 1);
  __m256  t95 = _mm256_cvtepi32_ps(tmp);
  return _mm256_add_ps(*((__m256*)v_a), t95);
}
float x[2000], y[2000];
float foo(float y[]) {
#pragma omp simd
  for (int k=0; k< 2000; k++) {
    x[k] = MyAdd(&y[k], k);
  }
  return x[0] + x[1999];

戻り値に 2 つ以上のレジスターが含まれる場合、次の方法で関数を正しく定義できます。

#include<immintrin.h>

typedef struct {
 __m256d r1;
 __m256d r2;
} __m256dx2;

__declspec(noinline)
double MyAdd(double* a, int b) { return *a + b; }

__declspec(vector_variant(implements(MyAdd(double *a, int b)),       
                          linear(a), vectorlength(8),
                          nomask, processor(core_2nd_gen_avx)))
__m256dx2 __regcall MyAddVec(double* v_a, __m128i v_b, __m128i v_b2) {
  __m256d t1 = _mm256_cvtepi32_pd(v_b);
  __m256d t2 = _mm256_cvtepi32_pd(v_b2);
  __m256dx2 ret;
  ret.r1 = _mm256_mul_pd(t1,*((__m256d*)v_a));
  ret.r2 = _mm256_mul_pd(t2,*(((__m256d*)v_a)+1));
  return ret;
}

__declspec(align(32)) double x[2000], y[2000];
double foo(double* y) {
#pragma omp simd
  for (int k=0; k< 2000; k++) {
    x[k] = MyAdd(y, k);
    y++;
  }
  return x[0] + x[1999];
}

関連情報