Performance 中断开销vs控制标志
我使用的是一个简单的素数生成函数。这段代码大约需要5.25秒来生成10k素数(设备_primes[0]保存已找到的素数,其余位置保存已找到的素数)Performance 中断开销vs控制标志,performance,cuda,Performance,Cuda,我使用的是一个简单的素数生成函数。这段代码大约需要5.25秒来生成10k素数(设备_primes[0]保存已找到的素数,其余位置保存已找到的素数) \u全局\uuuuuu无效getPrimes(int*设备\u primes,int n) { int c=0; int thread_id=blockIdx.x*blockDim.x+threadIdx.x; int num=线程id+2; 如果(线程id==0)设备素数[0]=1; __同步线程(); while(设备_素数[0]
\u全局\uuuuuu无效getPrimes(int*设备\u primes,int n)
{
int c=0;
int thread_id=blockIdx.x*blockDim.x+threadIdx.x;
int num=线程id+2;
如果(线程id==0)设备素数[0]=1;
__同步线程();
while(设备_素数[0] 对于(c=2;c,正如Tony所建议的,发散的代码执行可能会导致gpu代码的严重减速,迫使某些代码以串行方式而不是并行方式运行。在上面代码的慢速版本中,遇到中断的线程会与继续运行的代码发散
是gpu编程技术的良好资源:
任何流控制指令(if、switch、do、for、while)都会导致相同扭曲的线程发散(即遵循不同的执行路径),从而显著影响有效的指令吞吐量。如果发生这种情况,则必须序列化不同的执行路径,从而增加为此扭曲执行的指令总数。当所有不同的执行路径都完成时,线程会聚回同一执行路径
较新的nvidia硬件和cuda版本可以比旧版本更好地处理一些分支,但最好尽可能避免分支
_global__ void getPrimes(int *device_primes,int n)
{
int c = 0;
int thread_id = blockIdx.x * blockDim.x + threadIdx.x;
int num = thread_id+2;
if (thread_id == 0) device_primes[0] = 1;
__syncthreads();
while(device_primes[0] < n)
{
for (c = 2; c <= num - 1; c++)
{
if (num % c == 0) //not prime
{
break;
}
}
if (c == num) //prime
{
int pos = atomicAdd(&device_primes[0],1);
device_primes[pos] = num;
}
num += blockDim.x * gridDim.x; // Next number for this thread
}
}
for (c = 2; c <= num - 1; c++)
{
if (num % c == 0) //not prime
break;
}
if (c == num) {...}
int prime = 1;
...
for (c = 2; c <= num - 1 && prime; c++)
{
if (num % c == 0) prime = 0; // not prime
}
if (prime) {...} // if prime