本程序中,我以a[N]和 b[N]代表两个向量,其欧氏距离计算的串行C代码如下:
CODE:dis = 0;
for(int i = 0; i < N; i++){
dis += (a[i] - b[i]) * (a[i - b[i]);
}
dis = sqrt(dis);其中dis表示两个向量的距离,sqrt表示求平方根函数。从代码可以看出,我们可以使用N个线程,每个线程计算a,b一维上数据差的平方,但是由于这个计算量太小,为了加大计算量,我采用了一个线程计算多个数据差的平方和,在这步后,我们要将所有线程数据加起来以得到最终的结果,考虑到CUDA不支持全局同步而支持块内同步,因此我们可以先得到每个块的和,然后再将每个块的和保存到全局存储器d_temp中。最后再重新建立一个内核来将d_temp的数据求和,由于此时数据量小,因此只要一个块就够了。
考虑到分支会极大的影响到CUDA程序的性能,因此我们将块内各线程数据加和的方式是折半相加,此时可以利用高速的共享存储器。折半相加的思想是:假设有n = 2^k个线程,那么第一次相加在0和n/2, 1和n/2+1,……,n/2-1 和n-1之间进行。此后线程0至n/2-1拥有的数据和等于之前块内所有数据和,然后可以进行下一次折半相加。在再次折半相加之间为了保证数据一致性,必须使用__syncthreads()函数在块内所有线程间同步。具体代码如下: