在cuda执行一次代码的一部分

时间:2012-12-06 12:58:07

标签: c cuda

我想知道是否可以在GPU中执行静态语句

这是我的代码的一部分

__global__ void run_state(float *oldv, float* newv, float* w, int t)
{
  int i = threadIdx.x;

  nextState(i, oldv, newv, w, t);


  newv[0]   = newv[1];
  newv[N+1] = newv[N];

}

我想知道newv[0] = newv[1];newv[N+1] = newv[N];是否可以在nextState循环并且只执行一次后执行?

2 个答案:

答案 0 :(得分:1)

我不清楚你想要实现什么(按每个执行一次?),所以我会展示一些替代方案:

如果你想执行一个每个块的语句,你可以通过测试线程索引来做到这一点:

__syncthreads();
if ((threadIdx.x | threadIdx.y | threadIdx.z) == 0) {
    // statements that are only executed once per block
}
__syncthreads();

如果要执行一次每次内核调用语句,则需要更加具体地说明语句何时执行,因为内核的块没有按特定顺序执行。 / p>

上面示例的简单扩展产生了一个版本,其中语句在每次内核调用时执行一次,但是在未指定的时间:

if ((threadIdx.x | threadIdx.y | threadIdx.z
     | blockIdx.x | blockIdx.y | blockIdx.z) == 0) {
    // statements that are executed once per kernel invocation,
    // at an unspecified time
}

可以使用全局内存中的原子操作来指定语句何时执行,但代价是额外的全局内存带宽使用。为了限制性能影响,通常每个块只执行一次这些原子操作是个好主意。

如果你想在第一个块到达后立即执行语句,那么对全局标志的简单测试就足够了:

__global__ volatile unsigned int statementHasExecuted;

...

__syncthreads();
if ((threadIdx.x | threadIdx.y | threadIdx.z) == 0) {
    unsigned int state = atomicMin((unsigned int*)&statementHasExecuted, 1);
    if (state == 0) {
        // statements that are executed once per kernel invocation,
        // as soon as the first block reaches the statement

        // now make the results visible to the other blocks:
        __threadfence();
        // and signal that we are done:
        atomicMin((unsigned int*)&statementHasExecuted, 2);
    } else {
        while (state < 2) {
            // busy wait until execution of statement in other block has finished:
            state = statementHasExecuted;
        }
    }
}
__syncthreads();
每次内核启动前都需要将

statementHasExecuted重置为零。

你所追求的可能是相反的情况,一段代码仅在所有其他块完成后执行Appendix B.5 "Memory Fence Functions" of the Programming Guide为此提供了示例代码。

(请注意,所有代码都已在浏览器中编写,未经测试 - 可能包含错误)。

答案 1 :(得分:0)

您指定一个线程来完成最后的工作。例如:

__global__ void run_state(float *oldv, float* newv, float* w, int t)
{
  int i = threadIdx.x;

  nextState(i, oldv, newv, w, t);

  if (i == 0) {
    newv[0]   = newv[1];
    newv[N+1] = newv[N];
  }
}