UPDATE II:受け入れられた答えとコメントで提案されたアイデアを説明する2つの例を書いた。最初の1つは明示的な型付き操作を実行します。math_cmp.cc
1つの汎用カーネルを作成し、それを別のISAにマップする
// math_cmp.cc
#include <iostream>
#include <xmmintrin.h>
using namespace std;
int main()
{
float a, b;
cin >> a >> b;
float res = (a + b) * (a - b);
cout << res << endl;
__m128 a_vec, b_vec, res_vec;
a_vec = _mm_set1_ps(a);
b_vec = _mm_set1_ps(b);
res_vec = _mm_mul_ps(_mm_add_ps(a_vec, b_vec),
_mm_sub_ps(a_vec, b_vec));
float *res_ptr;
res_ptr = (float *) &res_vec;
for (int i = 0; i < 4; ++i)
cout << "RES[" << i << "]: " << res_ptr[i] << ' ';
cout << endl;
return 0;
}
第二ファイルmath_traits.cc
はテンプレート+はを形質行います。 -O3
でコンパイルしたときに生成されたアセンブリは、math_cmp.cc
のアセンブリとほぼ同じです。
// math_traits.cc
#include <iostream>
#include <xmmintrin.h>
using namespace std;
template <typename T>
class MathOps
{
};
template <typename T>
T kernel (T a, T b)
{
T res = MathOps<T>::mul(MathOps<T>::add(a, b), MathOps<T>::sub(a, b));
return res;
}
template <>
class MathOps <float>
{
public:
static float add (float a, float b)
{
return a + b;
}
static float sub (float a, float b)
{
return a - b;
}
static float mul (float a, float b)
{
return a * b;
}
};
template <>
class MathOps <__m128>
{
public:
static __m128 add (__m128 a, __m128 b)
{
return a + b;
}
static __m128 sub (__m128 a, __m128 b)
{
return a - b;
}
static __m128 mul (__m128 a, __m128 b)
{
return a * b;
}
};
int main()
{
float a, b;
cin >> a >> b;
cout << kernel<float>(a, b) << endl;
__m128 a_vec, b_vec, res_vec;
a_vec = _mm_set1_ps(a);
b_vec = _mm_set1_ps(b);
res_vec = kernel<__m128>(a_vec, b_vec);
float *res_ptr;
res_ptr = (float *) &res_vec;
for (int i = 0; i < 4; ++i)
cout << "RES[" << i << "]: " << res_ptr[i] << ' ';
cout << endl;
return 0;
}
I UPDATE:私は質問のようにまとめることができると思います。は「現代のC++のアプローチは、多型関数のようなマクロと等価であることはありますか?」
抽象操作で1つのカーネルを書き、自動的にISA固有のコードを生成するためにC++でプログラミングすることが可能になるのだろうか。例えば、一般的なカーネルが使用できます
RET_TYPE kernel(IN_TYPE a, IN_TYPE b)
{
RET_TYPE res = ADD(a, b);
return res;
}
とカーネルが両方にスカラーバージョン変換することができます。
float kernel(float a, float b)
{
float res = a + b;
return res;
}
とベクトル化バージョン:では
__m128 kernel(__m128 a, __m128 b)
{
__m128 res = _mm_add_ps(a, b);
return res;
}
を実際には、一般的なカーネルははるかに複雑になります。型の汎用性は、テンプレートパラメータによって処理できます。しかし、命令の一般性は私をつかまえました。
通常、この種の問題は、あなたには、いくつかの中間表現(IR)でプログラムを書くコード生成、介してアドレスされ、その後、様々なターゲット言語へのIR表現を翻訳します。
しかし、私は純粋で現代的な C++の中でそれをしなければならない、つまりCマクロを意味しない。 汎用プログラミング、テンプレートメタプログラミングまたはOOPで巧妙に悪用して達成できるかどうか疑問です。あなたはいくつかのポインタを持っている場合は助けてください!
C++でテンプレートベースの並列プログラミングの既存のライブラリを調査しましたか?あなたの最後の段落は、これが宿題であるかのように見えます。 – JAB
@JAB質問はC++の宿題の通常の範囲を超えていると思います。しかし私は間違っている可能性があります。最後の段落の制約は、既存のプロジェクト設計によるものです。 –
@JAB。アイデアを説明するための例を追加しました。それが意味をなさないかどうか私に教えてください。ありがとうございました。 –