我想知道是否可以在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
循环并且只执行一次后执行?
答案 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];
}
}