问题描述
我正在运行Hello World的Hybridizer-basic-samples示例,但是在GPU中执行所需的时间比cpu多。
[EntryPoint("run")]
public static void Run(int N,double[] a,double[] b)
{
Parallel.For(0,N,i => { a[i] += b[i]; });
}
static void Main(string[] args)
{
int N = 1024 * 1024 * 16;
double[] acuda = new double[N];
double[] adotnet = new double[N];
double[] b = new double[N];
Random rand = new Random();
for (int i = 0; i < N; ++i)
{
acuda[i] = rand.NextDouble();
adotnet[i] = acuda[i];
b[i] = rand.NextDouble();
}
cudaDeviceProp prop;
cuda.GetDeviceProperties(out prop,0);
HybRunner runner = HybRunner.Cuda().Setdistrib(prop.multiProcessorCount * 16,128);
dynamic wrapped = runner.Wrap(new Program());
// run the method on GPU
var watch = System.Diagnostics.Stopwatch.StartNew();
wrapped.Run(N,acuda,b);
watch.Stop();
Console.WriteLine($"Execution Time: {watch.ElapsedMilliseconds} ms");
// run .Net method
var watch2 = System.Diagnostics.Stopwatch.StartNew();
Run(N,adotnet,b);
watch2.Stop();
Console.WriteLine($"Execution Time: {watch2.ElapsedMilliseconds} ms");
}
当我运行程序时,GPU中Run()的执行时间总是比.Net方法更长。像GPU一样执行需要818毫秒,而cpu则需要89毫秒。原因?
解决方法
正如@InBetween所提到的,您可能正在测量编译器开销。进行预热过程以使所有代码都首先编译是一种很好的做法。或使用类似benchmarking.net的方法为您完成任务。
另一个可能的原因是开销。在GPU上运行时,系统需要将输入数据复制到GPU内存,然后再次将结果复制回去。可能还会涉及其他费用。将数字相加是非常简单的操作,因此处理器可能会以最大理论速度运行。
让我们做一些后面的信封计算。假设CPU每个时钟可以执行4次加法操作(即AVX256可以执行的操作)。每双4 * 8个字节=每个时钟32个字节,以及每秒4 * 10 ^ 9个时钟。这样可以提供128 GB / s的处理速度。这显着高于16 GB / s的PCIe 3 x16带宽。由于其他限制,您可能无法达到此速度,但它表明限制因素可能不是处理器本身,因此使用GPU可能无法改善性能。
使用更复杂的算法为每个数据项执行更多处理时,GPU处理应表现出更好的收益。