Kepler

时间:2016-11-18 12:29:26

标签: cuda

我正在研究Kepler GPU K40m上随机内存访问的性能。我使用的内核非常简单,如下所示,

__global__ void scatter(int *in1, int *out1, int * loc, const size_t n) {

    int globalSize = gridDim.x * blockDim.x;
    int globalId = blockDim.x * blockIdx.x + threadIdx.x;

    for (unsigned int i = globalId; i < n; i += globalSize) {
        int pos = loc[i];   
        out1[pos] = in1[i]; 
    }
}

也就是说,我将读取一个数组in1以及一个位置数组loc。然后我根据loc置换in1并输出到数组out1。通常,out1 [loc [i]] = in1 [i]。请注意,位置数组已经充分洗牌,每个元素都是唯一的。

我只使用默认的nvcc编译设置并打开-O3标志。 L1 dcache已禁用。另外,我将#块修复为8192,块大小为1024。

我使用nvprof来配置我的程序。很容易知道内核中的大多数指令都应该是内存访问。对于warp的指令,由于每个线程需要一个离散的4字节数据,因此应该多次重放指令(最多31次?)并发出多个内存事务以满足warp中所有线程的需要。但是,度量“inst_replay_overhead”似乎令人困惑:当#tuples n = 16M时,重放开销为13.97,这对我来说很有意义。但是当n = 600M时,重放开销变为34.68。即使是较大的数据,比如700M和800M,重播开销也将达到85.38和126.87。

根据文档,“inst_replay_overhead”的含义是“每条指令执行的平均重放次数”。这意味着当n = 800M时,平均每条指令被重放127次?怎么回放时间比31大得多?我是否误解了某些内容,或者我错过了其他因素,这些因素也会对重播时间产生重大影响?非常感谢!

1 个答案:

答案 0 :(得分:1)

您可能误解了指令重播的基本含义。

inst_replay_overhead包括发出指令的次数,但无法完成。这可能由于各种原因而发生,this answer中对此进行了解释。相关摘录摘自答案:

  

如果SM由于

而无法完成发出的指令      
      
  1. 常量高速缓存未命中立即常量(指令中引用的常量),
  2.   
  3. 在索引常量负载中解决分歧,
  4.   
  5. 解决全局/本地内存加载或存储中的分歧,
  6.   
  7. 银行冲突   共享内存加载或存储,
  8.   
  9. 解决原子或原子的冲突   减少操作,
  10.   
  11. 加载或存储操作需要数据   写入装载存储单元或从超出的装置读取   读/写总线宽度(例如128位加载或存储)或
  12.   
  13. 加载缓存未命中   (当数据在缓存中就绪时,会发生重放以获取数据)
  14.         

    然后   SM调度程序必须多次发出指令。这是   称为重播指令。

我猜这是因为您的案例中有分散的读取。这种指令重放的概念也存在于CPU方面。维基百科文章here