私は、関数テンプレートのインスタンシエーションを支援するフレームワークに取り組んできました。私は、実行時にインスタンス化して選択する必要がある、最適化のために整数値でテンプレート化されたたくさんの関数を持っています。 { {7, 0, 3, 4, 2}, {7, 0, 3, 4, 2}, {7, 0, 3, 4, 2} }
のすべての組み合わせで、3つの整数値をとるテンプレートインスタント化フレームワークのクリーンアップの助けが必要
// Function to instantiate templates of.
template<int a, int b, int c> void MyFunction(float, double){};
// List of values to substitute into each template parameter.
typedef mpl::vector_c< int, 7, 0, 3, 4, 2> valuesToInstantiate;
int numberOfValuesPerParameter = size<valuesToInstantiate>::type::value;
// Function pointer type. Must define type for array to hold template instantiations.
typedef void (*MyFunctionPointer)(float, double);
// Array to hold template instantiations.
// Accessed at runtime to get proper instantiation.
MyFunctionPointer arrayOfTemplateInstantiations[numberOfValuesPerParameter*numberOfValuesPerParameter*numberOfValuesPerParameter];
// Passed to template instantiation framework.
// AddTemplate member function will be called once per template value combo (3 int values).
// templateIndex indicates where to store the instantation in the array.
// templateSequence contains the template value combo (3 int values).
template<int templateIndex, typename templateSequence>
struct MyFunctionTemplateCreator
{
static void AddTemplate(void)
{
// Store template instantiation in array.
arrayOfTemplateInstantiations[templateIndex] = MyFunction
<
mpl::at<templateSequence, mpl::int_<0> >::type::value,
mpl::at<templateSequence, mpl::int_<1> >::type::value,
mpl::at<templateSequence, mpl::int_<2> >::type::value
>;
}
};
// List of lists where each inner list contains values to instantiate
// for the corresponding template parameter. E.g. each value in the first
// inner list will be passed into the first template parameter of MyFunction
typedef mpl::vector< valuesToInstantiate, valuesToInstantiate, valuesToInstantiate > templatesToCreate;
// Call template instantation framework to instantiate templates.
CreateTemplates<MyFunctionTemplateCreator, templatesToCreate> unusedVariable;
// Call proper template instantation at runtime...using index 5 arbitrarily for example.
arrayOfTemplateInstantiations[5](1.5, 2.0);
だから例では、私はインスタンス化していますMyFunctionを、:使用例は次のとおりです。私はかなり長いので、CreateTemplatesの実装を省略しましたが、boost MPL for_eachを使用して実装されています。上記のコードは私がこれをやりたいすべての関数に必要ですが、512の明示的なインスタンス化を書くよりも短いですが、まだ少しです。
驚いたことに、これを実行したい各関数用に書かれなければならない最長のコードは、関数ポインタのtypedefです。多くの関数は10個以上の引数を取るためです。これらのテンプレートのインスタンス化を、より包括的な型の配列に何らかの形でラップすることで格納する方法はありますか?
引数のために、テンプレートのパラメータが常に例のような整数値であると仮定することができます。これにより、テンプレートのインスタンス化のシグネチャが特定の関数テンプレートですべて同じになります。インスタンス化される関数はすべてグローバル名前空間にあり、メンバー関数ではありません(実際にはCUDAカーネルです)。これをきれいにするためのヒントをいただければ幸いです。
注:C++を使用して03
編集:私は、私が達成しようとしているものについてTarmoPikaroの質問に対処したいと考えました。
私は、最大4つのタスク/スレッドがGPUを共有して仕事をしているアプリケーション(同じ仕事、異なるデータ)で作業しています。私たちのCUDAカーネルのいくつかはテクスチャを使用しているので、実行時に利用可能なテクスチャを動的に出力する必要があります。従来のCUDA計算機能をサポートしていません。つまり、テクスチャオブジェクトを関数の引数として渡すことはできず、静的なグローバル変数でなければなりません。その後、CPUのタスク/スレッドにテクスチャを与えるために、我々は、テクスチャ指標を与え、私たちのCUDAカーネルのような文があります:カーネル内のループでその文を持つ
// (variables t_int_2d_N are texture objects)
if (maskTextureIndex == 0)
maskValue = tex2D(t_int_2d_0, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 1)
maskValue = tex2D(t_int_2d_1, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 2)
maskValue = tex2D(t_int_2d_2, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 3)
maskValue = tex2D(t_int_2d_3, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 4)
maskValue = tex2D(t_int_2d_4, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 5)
maskValue = tex2D(t_int_2d_5, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 6)
maskValue = tex2D(t_int_2d_6, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 7)
maskValue = tex2D(t_int_2d_7, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
を容認できないパフォーマンスの損失です。パフォーマンスの低下を避けるために、上記の条件文がコンパイルされるようにカーネルに整数値(テクスチャインデックスを表す)をテンプレート化します。上記のコードを含むカーネルは、0-7のmaskTextureIndexでインスタンス化されるため、実行時に8つの異なるカーネルを選択できます。私たちのカーネルの中には、最大3つのテクスチャを使用するものがあります。各テクスチャタイプ(float 1D、float 2D、float2 2D、int 3Dなど)はインデックス0-7を持ちます。つまり、8 * 8 * 8 =上記のような3つの異なる条件文をコンパイルするために512の異なるカーネル。私の元の質問のコードは、テクスチャを使用するカーネルごとに使用され、すべての組み合わせをインスタンス化するのに役立ちます。
残念ながら、プログラミング言語そのものは、もともとプログラミング言語の作者が考えなかったように、どのような方法でも調整できます。このような悪用や悪用の言葉は、ガイアに到達したと思う極端なプログラマーが可能であり、言葉を使いたいことを何でもすることができます。残念なことに、このようなコードは複雑になり、さらに発展し、次の反復では他の開発者があなたのソリューションを書き換える可能性が非常に高いです。最終的に達成したいことをより詳細に指定することができますか? – TarmoPikaro
@TarmoPikaro最後にあなたの質問に対処しました。 C++ 11にアップグレードすることなく、より良いソリューションがあるかどうかはわかりません。誰かが挑戦としてそれを取ることを望む;)。 – user1777820