我正在研究C#庫,它使用NVIDIA的CUDA將某些工作任務卸載到GPU。這樣的一個例子是添加一起使用的擴展方法的兩個陣列:如何阻塞,直到異步作業完成
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;
}
}
傳遞給構造函數的Action是一個在GPU上執行實際工作的異步方法。嵌套的Action是異步回調方法。
我主要關心的是如何最好/最優雅地處理轉換器中的等待問題,以及是否有更合適的方法來整體解決問題。如果需要進一步闡述或解釋,請留下評論。