无创dna是检查什么的| 喉炎吃什么药最有效| 脚背有痣代表什么| 吃什么可以增加免疫力| 做爱吃什么药| 木冉读什么| 心脏造影是什么| 苍耳是什么东西| 金不换是什么| 伊犁在新疆什么位置| 尿培养是检查什么病| 石榴什么时候开花| 魔鬼是什么意思| 千丝万缕是什么意思| 血小板低会引发什么病| 乌龟一般吃什么| 海关是什么| 桃符指的是什么| 有鳞状细胞是什么意思| 腰两侧疼痛是什么原因| ptt是什么| 大姨妈期间适合吃什么| 开胸手术吃什么补元气| 肉便器是什么意思| 产能过剩是什么意思| 粉荷花的花语是什么| 减肥为什么让早上空腹喝咖啡| 吃什么养肝护肝效果最好| 宫颈肥大是什么原因| 三七有什么功效和作用| 大腿外侧麻木是什么原因| 打葡萄糖点滴有什么用| 世侄是什么意思| 椰土是什么| 吃苹果是什么意思| 内心孤独的人缺少什么| 生姜泡水喝有什么好处| 吃什么可以止咳化痰| 梦见掉粪坑里了是什么意思| 味淋是什么东西| 吃什么降血糖最快| 负压是什么意思| 女性吃金蝉有什么好处| 梦见在天上飞是什么意思| 峻字五行属什么| 芒果什么品种最好吃| 被孤立的一般是什么人| 本科是什么意思| 什么动作容易怀孕| 高血压药什么时候吃最好| 什么时候测血压最准| 叶酸片有什么作用| 甲亢和甲状腺有什么区别| 呼吸道感染用什么药| 君子兰有什么特点| 预祝是什么意思| 80年出生属什么生肖| 警察是什么编制| 中产阶级的标准是什么| 老板娘是什么意思| 总爱放屁是什么原因| 随心而欲是什么意思| 周易和易经有什么区别| 跑步后尿血是什么情况| 1908年中国发生了什么| 血红蛋白偏低是什么意思| 宝石蓝是什么颜色| 梦见蛇吃人代表什么预兆| 兔子为什么不吃窝边草| 言外之意是什么意思| 打摆子是什么病| 梦见葡萄是什么意思| 鬼节会开什么生肖| 北京五行属什么| 甲状腺4级是什么意思| 脂蛋白a高有什么危害| 尿酸高有什么症状| 什么是幽门螺旋杆菌| 松花粉对肝有什么好处| 印第安纹是什么| 瘫痪是什么意思| 佛光普照什么意思| 和解少阳是什么意思| 最可爱的动物是什么生肖| 声音嘶哑吃什么药| 喝什么养胃| 肠胃属于什么科| 痰湿阻滞吃什么中成药| 艮为什么读yin| 跑步什么时候跑最好| 血管是什么颜色的| swag什么意思| 摩纳哥为什么这么富| 后背有痣代表什么意思| 凤凰指什么生肖| 香蕉和什么不能一起吃| 瓦是什么的单位| 荷叶茶有什么作用| 头皮长疙瘩是什么原因| 减肥可以吃什么水果| 睡觉老是流口水是什么原因| 倒班什么意思| 女性肾火旺有什么症状| 肌酐高是什么病| 进国企需要什么条件| 女人更年期有什么症状| 什么病会传染| 六点是什么时辰| 沉住气是什么意思| 刚生完孩子的产妇吃什么水果好| 1995年属什么| 一个鸟一个木念什么| 租赁费计入什么科目| 俊俏什么意思| 晚上睡不着是什么原因| 慢性宫颈炎是什么原因引起的| 什么样的空气| 生猴子是什么意思| 泌尿系感染吃什么药| 眼圈黑是什么原因| 36周检查什么项目| 木槿花的花语是什么| 千年杀是什么| 电磁炉滴滴响不加热是什么原因| 发烧打冷颤是什么原因| 胎监不过关是什么原因| 阑尾炎是什么原因引起的| 美容美体是干什么的| 319是什么意思| 天津市市长是什么级别| 茗字五行属什么| 尿频吃什么药最好| 蛋白糖是什么糖| 国防部部长是什么级别| 出汗太多是什么原因| 无为而治什么意思| 红薯是什么茎| 上皮细胞一个加号什么意思| 出轨是什么意思| 早晨起来嘴苦是什么原因| 小老头是什么意思| 小孩喉咙发炎吃什么药好| 抱薪救火是什么意思| 殿后和垫后有什么区别| 粥配什么菜最好吃| 防风通圣颗粒治什么病| psd是什么意思| 男人怕冷是什么原因| 蓝色的小药丸是什么药| 右下眼皮跳是什么原因| 小肚子疼是什么原因| 头发全白是什么病| 无创是什么| 100分能上什么大学| 焦虑症吃什么| 炒什么菜好吃又简单| 细菌性炎症用什么药| 脚麻木是什么病的前兆| 什么食物补肾| 痈疽是什么意思| o型b型生的孩子是什么血型| 睫角守宫吃什么| cto是什么职位| 长期便秘是什么原因引起的| 老是打饱嗝是什么原因| 维生素c什么时候吃最好| 云加一笔是什么字| 过氧化氢浓度阳性是什么意思| 红色尿液是什么原因| 有什么蔬菜| 一什么湖面| hgb是什么意思| 头发油的快是什么原因| 手背上长痣代表什么| 什么牌子的耳机音质效果最好| 九四年属什么生肖| 91网站是什么| 闺六月是什么意思| 反应性细胞改变炎症是什么意思| pd是什么元素| 妈妈咪呀是什么意思| 博美犬吃什么狗粮最好| 台湾什么时候收复| o2o是什么意思| 喝山楂泡水有什么功效| 晚上口苦是什么原因引起的| jbp什么意思| 什么什么为难| 世家是什么意思| 大学211和985是什么意思| 什么是手机号| 阴雨连绵是什么意思| 天蝎男和什么星座最配| 感染乙肝病毒有什么症状| 属鼠五行属什么| 子宫内膜厚吃什么药| 执念是什么意思| 转隶是什么意思| 心肌酶高有什么危害| 小便尿不出来什么原因| 吃什么可以增大阴茎| 蟑螂对人体有什么危害| 咳嗽看什么科| 倾国倾城是什么生肖| 什么叫心肌桥| 八面玲珑是什么意思| 捡漏什么意思| 人黑穿什么颜色的衣服好看| 十二月八号是什么星座| 金字旁土念什么字| 肝胆挂什么科| 花圃是什么意思| 印模是什么意思| 适得其反什么意思| 羊肉饺子馅配什么蔬菜最好吃| 横纹肌溶解症是什么原因造成的| 小朋友口臭是什么原因| 手比脸白是什么原因| 每次上大便都出血是什么原因| 梦见找鞋子是什么意思| 39属什么| 子宫肌瘤有什么危害| 3D硬金是什么意思| 破伤风是什么| 尾盘拉升意味着什么| 肺活量是什么意思| 黄色裤子搭配什么颜色上衣| 榴莲不可以和什么一起吃| 热得像什么| 痛风吃什么药好| 怀孕初期吃什么水果好| 定义是什么| 术后吃什么| 眼睛有眼屎是什么原因引起的| 喷砂是什么意思| 下面有异味用什么药| 青春不散场什么意思| 暇步士是什么档次品牌| 水瓶座女生和什么星座男生最配| 什么时候闰五月| 九岁属什么生肖| 不安腿综合征吃什么药| 百日咳是什么| 多米诺骨牌是什么意思| 肠胃不好喝什么茶| 贡中毒有什么症状| 马来酸曲美布汀片什么时候吃| 甲钴胺片是治什么的| 背部长痘痘是什么原因造成| 低血糖是什么原因| 腿浮肿是什么原因| 色拉油是什么| 中将相当于什么级别| 腱鞘炎什么症状| 蛇用什么呼吸| 心衰是什么病| 办居住证需要什么| 阳气不足吃什么中成药| 尿隐血挂什么科| 痛风吃什么水果最好| 肾积水挂什么科| 为什么受伤总是我| 发改委主任什么级别| 胎盘前壁是什么意思| 百度
Simulation / Modeling / Design

2017年四季度就业情况排名出炉 这些行业就业景气

百度 十九大闭幕的第三天,2017年10月27日,十九届中共中央政治局召开会议,审议《中共中央政治局关于加强和维护党中央集中统一领导的若干规定》和《中共中央政治局贯彻落实中央八项规定的实施细则》,明确加强和维护党中央集中统一领导,首先是中央领导层的政治责任,中央政治局全体同志要牢固树立四个意识,坚定四个自信。

In the previous two posts we looked at how to move data efficiently between the host and device. In this sixth post of our CUDA C/C++ series we discuss how to efficiently access device memory, in particular global memory, from within kernels.

There are several kinds of memory on a CUDA device, each with different scope, lifetime, and caching behavior. So far in this series we have used global memory, which resides in device DRAM, for transfers between the host and device as well as for the data input to and output from kernels. The name global here refers to scope, as it can be accessed and modified from both the host and the device. Global memory can be declared in global (variable) scope using the __device__ declaration specifier as in the first line of the following code snippet, or dynamically?allocated using cudaMalloc() and assigned to a regular C pointer variable as in line 7. Global memory allocations?can persist for the lifetime of the application. Depending on the compute capability of the device, global memory may or may not be cached on the chip.

__device__ int globalArray[256];

void foo()
{
    ...
    int *myDeviceMemory = 0;
    cudaError_t result = cudaMalloc(&myDeviceMemory, 256 * sizeof(int));
    ...
}

Before we go into global memory access performance, we need to refine our understanding of the CUDA execution model. We have discussed how threads are grouped into thread blocks, which are assigned to multiprocessors on the device. During execution there is a finer grouping of threads into warps. Multiprocessors on the GPU execute instructions for each warp in SIMD (Single Instruction Multiple Data) fashion. The warp size (effectively the SIMD width) of all current CUDA-capable GPUs is 32 threads.

Global Memory Coalescing

Grouping of threads into warps is not only relevant to computation, but also to global memory accesses. The device coalesces?global memory loads and stores issued by threads of a warp into as few transactions as possible to minimize DRAM bandwidth (on older hardware of compute capability less than 2.0, transactions are coalesced within half warps of 16 threads rather than whole warps). To make clear the conditions under which coalescing occurs across CUDA device architectures we run some simple experiments on three Tesla cards: a Tesla C870 (compute capability 1.0), a Tesla C1060 (compute capability 1.3), and a Tesla C2050 (compute capability 2.0).

We run two experiments that use variants of an increment kernel shown in the following code (also available on GitHub), one with an array offset that can cause misaligned accesses to the input array, and the other with strided accesses to the input array.

#include 
#include 

// Convenience function for checking CUDA runtime API results
// can be wrapped around any runtime API call. No-op in release builds.
inline
cudaError_t checkCuda(cudaError_t result)
{
#if defined(DEBUG) || defined(_DEBUG)
  if (result != cudaSuccess) {
    fprintf(stderr, "CUDA Runtime Error: %sn", cudaGetErrorString(result));
    assert(result == cudaSuccess);
  }
#endif
  return result;
}

template 
__global__ void offset(T* a, int s)
{
  int i = blockDim.x * blockIdx.x + threadIdx.x + s;
  a[i] = a[i] + 1;
}

template 
__global__ void stride(T* a, int s)
{
  int i = (blockDim.x * blockIdx.x + threadIdx.x) * s;
  a[i] = a[i] + 1;
}

template 
void runTest(int deviceId, int nMB)
{
  int blockSize = 256;
  float ms;

  T *d_a;
  cudaEvent_t startEvent, stopEvent;

  int n = nMB*1024*1024/sizeof(T);

  // NB:  d_a(33*nMB) for stride case
  checkCuda( cudaMalloc(&d_a, n * 33 * sizeof(T)) );

  checkCuda( cudaEventCreate(&startEvent) );
  checkCuda( cudaEventCreate(&stopEvent) );

  printf("Offset, Bandwidth (GB/s):n");

  offset<<>>(d_a, 0); // warm up

  for (int i = 0; i <= 32; i++) {
    checkCuda( cudaMemset(d_a, 0.0, n * sizeof(T)) );

    checkCuda( cudaEventRecord(startEvent,0) );
    offset<<>>(d_a, i);
    checkCuda( cudaEventRecord(stopEvent,0) );
    checkCuda( cudaEventSynchronize(stopEvent) );

    checkCuda( cudaEventElapsedTime(&ms, startEvent, stopEvent) );
    printf("%d, %fn", i, 2*nMB/ms);
  }

  printf("n");
  printf("Stride, Bandwidth (GB/s):n");

  stride<<>>(d_a, 1); // warm up
  for (int i = 1; i <= 32; i++) {
    checkCuda( cudaMemset(d_a, 0.0, n * sizeof(T)) );

    checkCuda( cudaEventRecord(startEvent,0) );
    stride<<>>(d_a, i);
    checkCuda( cudaEventRecord(stopEvent,0) );
    checkCuda( cudaEventSynchronize(stopEvent) );

    checkCuda( cudaEventElapsedTime(&ms, startEvent, stopEvent) );
    printf("%d, %fn", i, 2*nMB/ms);
  }

  checkCuda( cudaEventDestroy(startEvent) );
  checkCuda( cudaEventDestroy(stopEvent) );
  cudaFree(d_a);
}

int main(int argc, char **argv)
{
  int nMB = 4;
  int deviceId = 0;
  bool bFp64 = false;

  for (int i = 1; i < argc; i++) {    
    if (!strncmp(argv[i], "dev=", 4))
      deviceId = atoi((char*)(&argv[i][4]));
    else if (!strcmp(argv[i], "fp64"))
      bFp64 = true;
  }

  cudaDeviceProp prop;

  checkCuda( cudaSetDevice(deviceId) )
  ;
  checkCuda( cudaGetDeviceProperties(&prop, deviceId) );
  printf("Device: %sn", prop.name);
  printf("Transfer size (MB): %dn", nMB);

  printf("%s Precisionn", bFp64 ? "Double" : "Single");

  if (bFp64) runTest(deviceId, nMB);
  else       runTest(deviceId, nMB);
}

This code can run both offset and stride kernels in either single (default) or double precision by passing the “fp64” command line option. Each kernel takes two arguments, an input array and an integer representing the offset or stride used to access the elements of the array. The kernels are called in loops over a range of offsets and strides.

Misaligned Data Accesses

The results for the offset kernel on the Tesla C870, C1060, and C2050 appear?in the following figure.

Arrays allocated in device memory are aligned to 256-byte memory segments by the CUDA driver. The device can access global memory via 32-, 64-, or 128-byte transactions that are aligned to their size. For the C870 or any other device with a compute capability of 1.0, any misaligned access by a half warp of threads (or aligned access where the threads of the half warp do not access memory in sequence) results in 16 separate 32-byte transactions. Since only 4 bytes are requested per 32-byte transaction, one would expect the effective bandwidth to be reduced by a factor of eight, which is roughly what we see in the figure above (brown line) for offsets that are not a multiple of 16 elements, corresponding to one half warp of threads.

For the Tesla C1060 or other devices with compute capability of 1.2 or 1.3, misaligned accesses are less problematic. Basically, the misaligned accesses of contiguous data by a half warp of threads are serviced in a few transactions that “cover” the requested data. There is still a performance penalty relative to the aligned case due both to unrequested data being transferred and to some overlap of data requested by different half-warps, but the penalty is far less than for the C870.

Devices of compute capability 2.0, such as the Tesla C2050, have an L1 cache in each multiprocessor with a 128-byte line size. The device coalesces accesses by threads in a warp into as few cache lines as possible, resulting in negligible effect of alignment on throughput for sequential memory accesses across threads.

Strided Memory Access

The results of the stride kernel appear in the following figure.

For strided global memory access we have a different picture. For large strides, the effective bandwidth is poor regardless of architecture version. This should not be surprising: when concurrent threads simultaneously access memory addresses that are very far apart in physical memory, then there is no chance for the hardware to combine the accesses. You can see in the figure above that on the Tesla C870 any stride other than 1 results in drastically reduced effective bandwidth. This is because compute capability 1.0 and 1.1 hardware requires linear, aligned accesses across threads for coalescing, so we see the familiar 1/8 bandwidth that we also saw in the offset kernel. Compute capability 1.2 and higher hardware can coalesce accesses that fall into aligned segments (32, 64, or 128 byte segments on CC 1.2/1.3, and 128-byte cache lines on CC 2.0 and higher), so this hardware results in a smooth bandwidth curve.

When accessing multidimensional arrays it is often necessary for threads to index the higher dimensions of the array, so strided access is simply unavoidable. We can handle these cases by using a type of CUDA memory called shared memory. Shared memory is an on-chip memory shared by all threads in a thread block. One use of shared memory is to extract a 2D tile of a multidimensional array from global memory in a coalesced fashion into shared memory, and then have contiguous threads stride through the shared memory tile. Unlike global memory, there is no penalty for strided access of shared memory. We will cover shared memory in detail in the next post.

?Summary

In this post we discussed some aspects of how to efficiently access global memory from within CUDA kernel code. Global memory access on the device shares performance characteristics with data access on the host; namely, that data locality is very important. In early CUDA hardware, memory access alignment was as important as locality across threads, but on recent hardware alignment is not much of a concern. On the other hand, strided memory access can hurt performance, which can be alleviated using on-chip shared memory. In the next post we will explore shared memory in detail, and in the post after that we will show how to use shared memory to avoid strided global memory accesses during a matrix transpose.

Discuss (7)

Tags

月经期间吃什么最好 梨什么时候成熟 什么是阴吹 缄默什么意思 出生证号是什么
臆想症是什么 手指甲紫色是什么原因 豆粕是什么东西 龙眼是什么季节的水果 冬瓜烧什么好吃
肾错构瘤是什么原因引起的 提前来大姨妈是什么原因 脚底长痣有什么说法 厕所里应该摆什么花 1月1号什么星座
7.17是什么日子 阎维文什么军衔 懵懂少年是什么意思 皮肤软组织感染是什么意思 吞咽困难是什么原因造成的
什么是无精症hcv8jop6ns8r.cn 消防队属于什么编制hcv7jop6ns0r.cn 三伏贴什么时候贴hcv7jop9ns9r.cn 化验血能查出什么项目hcv8jop9ns3r.cn 心火旺失眠吃什么药hcv8jop5ns4r.cn
吃榴莲不能和什么一起吃hcv7jop9ns3r.cn 蜡笔小新的爸爸叫什么hcv7jop9ns9r.cn 双性恋是什么hcv8jop5ns8r.cn 清蒸什么鱼好吃hcv7jop5ns3r.cn 反酸水吃什么药hcv9jop4ns8r.cn
入睡困难吃什么药效果最好hcv9jop3ns4r.cn 配菜是什么意思xjhesheng.com 吃什么对皮肤好还能美白的hcv7jop7ns4r.cn 生孩子需要准备什么东西hcv8jop6ns4r.cn 农历五月初五是什么节日cj623037.com
解脲支原体阳性是什么意思inbungee.com dior是什么意思hcv9jop6ns4r.cn 白蛋白偏高是什么原因hcv8jop2ns4r.cn 糖尿病人喝什么茶最好hcv8jop3ns2r.cn 查甲状腺挂什么科hcv9jop6ns0r.cn
百度