如何计算整个CUDA内核执行的执行线程数?

时间:2013-05-28 11:40:19

标签: cuda

我想逐渐计算整个内核执行的线程执行次数。是否有本地计数器或有没有其他方法可以做到这一点?我知道保留一个全局变量并且每个线程的增量都不会起作用,因为全局内存中的变量不能保证线程的同步访问。

3 个答案:

答案 0 :(得分:8)

有许多方法可以衡量线程级执行效率。这个答案提供了不同收集机制的列表。 Robert Crovella的答案提供了一种手动仪器方法,可以准确地收集信息。类似的技术可用于收集内核中的差异信息。

为执行启动的线程数(静态)

gridDim.x * gridDim.y * gridDim.z * blockDim.x * blockDim.y * blockDim.z

推出的主题数量

gridDim.x * gridDim.y * gridDim.z * ROUNDUP((blockDim.x * blockDim.y * blockDim.z),WARP_SIZE)

此数字包括在warp的生命周期内处于非活动状态的线程。

这可以使用PM计数器threads_launched收集。

已执行变形说明

计数器inst_executed计算执行/退出的扭曲指令的数量。

发布变形说明

计数器inst_issued计算发出的指令数。 inst_issued> = inst_executed。为了处理对窄执行单元的调度或处理共享存储器和L1操作中的地址差异,一些指令将被执行多次,每次执行指令。

执行的线程指令

计数器thread_inst_executed计算执行的线程指令数。可以使用thread_inst_executed / inst_executed导出指标avg_threads_executed_per_instruction。此计数器的最大值为WARP_SIZE。

未预测脱线程执行指令

计算能力2.0及以上设备使用指令预测来禁用warp中线程的回写,作为短序列发散指令的性能优化。

计数器not_predicated_off_thread_inst_executed计算所有线程执行的指令数。此计数器仅适用于计算能力3.0及更高版本的设备。

not_predicated_off_thread_inst_executed< = thread_inst_executed< = WARP_SIZE * inst_executed

由于thread_inst_executed和not_predicated_off_thread_inst_execucuted计数器中存在小错误,因此某些芯片上的关系会稍微偏离。

<强>廓

Nsight Visual Studio Edition 2.x支持收集上述计数器。

Nsight VSE 3.0支持新的指令计数实验,该实验可以收集每个SASS指令统计信息并以表格形式或高级源,PTX或SASS代码旁边显示数据。信息从SASS汇总到高级别来源。汇总的质量取决于编译器输出高质量符号信息的能力。建议您始终同时查看源和SASS。该实验可以收集以下每条指令统计信息:

一个。 inst_executed 湾thread_inst_executed(或活动掩码) C。 not_predicated_off_thread_inst_executed(活动谓词掩码) d。 active_mask的直方图 即predicate_mask的直方图

Visual Profiler 5.0可以准确地收集上述SM计数器。 nvprof可以收集并显示每个SM的详细信息。 Visual Profiler 5.x不支持Nsight VSE 3.0中可用的每条指令统计信息的收集。较旧版本的Visual Profiler和CUDA命令行分析器可以收集许多上述计数器,但结果可能不如5.0及以上版本的工具那样准确。

答案 1 :(得分:3)

也许是这样的:

__global__ void mykernel(int *current_thread_count, ...){
  atomicAdd(current_thread_count, 1);
  // the rest of your kernel code
  }


int main() {
  int tally, *dev_tally;
  cudaMalloc((void **)&dev_tally, sizeof(int));
  tally = 0;
  cudaMemcpy(dev_tally, &tally, sizeof(int), cudaMemcpyHostToDevice);
  ....
  // set up block and grid dimensions, etc.
  dim3 grid(...);
  dim3 block(...)

  mykernel<<<grid, block>>>(dev_tally, ...);
  cudaMemcpy(&tally, dev_tally, sizeof(int), cudaMemcpyDeviceToHost); 
  printf("total number of threads that executed was: %d\n", tally);
  ....

  return 0;
  }

您可以阅读有关原子函数here

的更多信息

评论中许多人表达混淆的部分原因是,当mykernel完成时(假设它成功运行),每个人都希望tally最终得到一个等于{{的值1}}

答案 2 :(得分:0)

我认为没有办法计算特定路径分支中的线程数。对于直方图的ex,最好有以下内容:

PS:直方图是关于计算每种颜色的像素。

for (i=0; i<256; i++) // 256 colors, 1 pixel = 1 thread if (threadidx.x == i) Histogramme[i] = CUDA_NbActiveThreadsInBranch() // Threads having i as color