NVIDIA の CUDA を使用して特定の作業タスクを GPU にオフロードする C# ライブラリに取り組んでいます。この例は、拡張メソッドを使用して 2 つの配列を一緒に追加することです。
float[] a = new float[]{ ... }
float[] b = new float[]{ ... }
float[] c = a.Add(b);
このコードの作業は GPU 上で行われます。ただし、結果が必要な場合にのみCPUブロックでコードが実行されるように、非同期で実行したいと思います(結果がまだGPUで終了していない場合)。これを行うために、非同期実行を隠す ExecutionResult クラスを作成しました。使用中、これは次のようになります。
float[] a = new float[]{ ... }
float[] b = new float[]{ ... }
ExecutionResult res = a.Add(b);
float[] c = res; //Implicit converter
最後の行で、データの準備がまだ完了していない場合、プログラムはブロックされます。スレッドの同期などの経験があまりないため、ExecutionResult クラス内でこのブロッキング動作を実装する最善の方法については確信が持てません。
public class ExecutionResult<T>
{
private T[] result;
private long computed = 0;
internal ExecutionResult(T[] a, T[] b, Action<T[], T[], Action<T[]>> f)
{
f(a, b, UpdateData); //Asych call - 'UpdateData' is the callback method
}
internal void UpdateData(T[] data)
{
if (Interlocked.Read(ref computed) == 0)
{
result = data;
Interlocked.Exchange(ref computed, 1);
}
}
public static implicit operator T[](ExecutionResult<T> r)
{
//This is obviously a stupid way to do it
while (Interlocked.Read(ref r.computed) == 0)
{
Thread.Sleep(1);
}
return result;
}
}
コンストラクターに渡されるアクションは、GPU で実際の作業を実行する非同期メソッドです。ネストされた Action は、非同期コールバック メソッドです。
私の主な関心事は、コンバーターで行われる待機を最適/最もエレガントに処理する方法ですが、問題全体を攻撃するためのより適切な方法があるかどうかです。さらに詳しく説明したり説明したりする必要がある場合は、コメントを残してください。