▶ 本章介绍了手动实现原子操作。重构了第五章向量点积的过程。核心是通过定义结构Lock及其运算,实现锁定,读写,解锁的过程。

● 章节代码

  1. #include <stdio.h>
  2. #include "cuda_runtime.h"
  3. #include "device_launch_parameters.h"
  4. #include "cuda.h"
  5. #include "D:\Code\CUDA\book\common\book.h"
  6.  
  7. #define imin(a,b) (a<b?a:b)
  8. #define sum_squares(x) (x*(x+1)*(2*x+1)/6)
  9. #define N 33 * 1024 * 1024
  10. #define THREADSIZE 256
  11. #define BLOCKSIZE imin(32, (N + THREADSIZE - 1) / THREADSIZE)
  12.  
  13. struct Lock
  14. {
  15. int *mutex;
  16. Lock(void)
  17. {
  18. int state = ;
  19. cudaMalloc((void **)&mutex, sizeof(int));
  20. cudaMemcpy(mutex, &state, sizeof(int), cudaMemcpyHostToDevice);
  21. }
  22. ~Lock(void)
  23. {
  24. cudaFree(mutex);
  25. }
  26. __device__ void lock(void)
  27. {
  28. while (atomicCAS(mutex, , ) != );
  29. //atomicCAS(a, b, c)将判断变量a是否等于b,
  30. //若相等,则用c的值去替换a,并返回c的值;若不相等,则返回a的值
  31. //函数lock()中,线程不断尝试判断mutex是否为0,
  32. //若为0则改写为1 ,表明“占用”,禁止其他线程进行访问
  33. //若为1则继续尝试判断
  34. }
  35. __device__ void unlock(void)
  36. {
  37. atomicExch(mutex, );
  38. //atomicExch(a, b)返回第一个变量的值,并将两个变量的值进行交换
  39. //这里使用原子操作只是与上面的atomicCAS统一,否则可以直接用赋值语句
  40. //线程操作完成,将mutex改写回0,允许其他线程进行访问
  41. }
  42. };
  43.  
  44. __global__ void dot(Lock lock, float *a, float *b, float *c)
  45. {
  46. __shared__ float share[THREADSIZE];
  47. int tid = threadIdx.x + blockIdx.x * blockDim.x;
  48. int cacheIndex = threadIdx.x;
  49. float temp = ;
  50.  
  51. while (tid < N)
  52. {
  53. temp += a[tid] * b[tid];
  54. tid += blockDim.x * gridDim.x;
  55. }
  56.  
  57. share[cacheIndex] = temp;
  58. __syncthreads();
  59.  
  60. int i = blockDim.x / ;
  61. while (i != )
  62. {
  63. if (cacheIndex < i)
  64. share[cacheIndex] += share[cacheIndex + i];
  65. __syncthreads();
  66. i /= ;
  67. }
  68. if (cacheIndex == )
  69. {
  70. lock.lock();// 等待可写入的机会,锁上,写入,再解锁
  71. *c += share[];
  72. lock.unlock();
  73. }
  74. }
  75.  
  76. int main(void)
  77. {
  78. float *a, *b, c = ;
  79. float *dev_a, *dev_b, *dev_c;
  80.  
  81. a = (float*)malloc(N * sizeof(float));
  82. b = (float*)malloc(N * sizeof(float));
  83.  
  84. cudaMalloc((void**)&dev_a, N * sizeof(float));
  85. cudaMalloc((void**)&dev_b, N * sizeof(float));
  86. cudaMalloc((void**)&dev_c, sizeof(float));
  87.  
  88. for (int i = ; i < N; i++)
  89. {
  90. a[i] = i;
  91. b[i] = i * ;
  92. }
  93.  
  94. cudaMemcpy(dev_a, a, N * sizeof(float), cudaMemcpyHostToDevice);
  95. cudaMemcpy(dev_b, b, N * sizeof(float), cudaMemcpyHostToDevice);
  96. cudaMemcpy(dev_c, &c, sizeof(float), cudaMemcpyHostToDevice);
  97.  
  98. Lock lock;
  99. dot << <BLOCKSIZE, THREADSIZE >> > (lock, dev_a, dev_b, dev_c);
  100.  
  101. cudaMemcpy(&c, dev_c, sizeof(float), cudaMemcpyDeviceToHost);
  102.  
  103. printf("\n\tAnswer:\t\t%.6g\n\tGPU value:\t%.6g\n", * sum_squares((float)(N - )), c);
  104.  
  105. free(a);
  106. free(b);
  107. cudaFree(dev_a);
  108. cudaFree(dev_b);
  109. cudaFree(dev_c);
  110. getchar();
  111. return ;
  112. }

《GPU高性能编程CUDA实战》附录一 高级原子操作的更多相关文章

  1. [问题解决]《GPU高性能编程CUDA实战》中第4章Julia实例“显示器驱动已停止响应,并且已恢复”问题的解决方法

    以下问题的出现及解决都基于"WIN7+CUDA7.5". 问题描述:当我编译运行<GPU高性能编程CUDA实战>中第4章所给Julia实例代码时,出现了显示器闪动的现象 ...

  2. 《GPU高性能编程CUDA实战》附录二 散列表

    ▶ 使用CPU和GPU分别实现散列表 ● CPU方法 #include <stdio.h> #include <time.h> #include "cuda_runt ...

  3. 《GPU高性能编程CUDA实战》附录四 其他头文件

    ▶ cpu_bitmap.h #ifndef __CPU_BITMAP_H__ #define __CPU_BITMAP_H__ #include "gl_helper.h" st ...

  4. 《GPU高性能编程CUDA实战》附录三 关于book.h

    ▶ 本书中用到的公用函数放到了头文件book.h中 #ifndef __BOOK_H__ #define __BOOK_H__ #include <stdio.h> #include &l ...

  5. 《GPU高性能编程CUDA实战》第十一章 多GPU系统的CUDA C

    ▶ 本章介绍了多设备胸膛下的 CUDA 编程,以及一些特殊存储类型对计算速度的影响 ● 显存和零拷贝内存的拷贝与计算对比 #include <stdio.h> #include " ...

  6. 《GPU高性能编程CUDA实战》第五章 线程并行

    ▶ 本章介绍了线程并行,并给出四个例子.长向量加法.波纹效果.点积和显示位图. ● 长向量加法(线程块并行 + 线程并行) #include <stdio.h> #include &quo ...

  7. 《GPU高性能编程CUDA实战》第四章 简单的线程块并行

    ▶ 本章介绍了线程块并行,并给出两个例子:长向量加法和绘制julia集. ● 长向量加法,中规中矩的GPU加法,包含申请内存和显存,赋值,显存传入,计算,显存传出,处理结果,清理内存和显存.用到了 t ...

  8. 《GPU高性能编程CUDA实战》第八章 图形互操作性

    ▶ OpenGL与DirectX,等待填坑. ● basic_interop #include <stdio.h> #include "cuda_runtime.h" ...

  9. 《GPU高性能编程CUDA实战》第七章 纹理内存

    ▶ 本章介绍了纹理内存的使用,并给出了热传导的两个个例子.分别使用了一维和二维纹理单元. ● 热传导(使用一维纹理) #include <stdio.h> #include "c ...

随机推荐

  1. 洛谷 1192:台阶问题(递推,DP)

    题目描述 有 N 级的台阶,你一开始在底部,每次可以向上迈最多 K 级台阶(最少 1 级),问到达第 N 级台阶有多少种不同方式. 输入输出格式 输入格式: 两个正整数N,K. 输出格式: 一个正整数 ...

  2. zzuli2228: 神奇的排名

    题目描述 小明最近沉迷上了打codeforces的比赛,和acm不同的是,这种比赛是积分制的,按照做题用时,错误次数以及hack来计分的.在某一场比赛,共有n个人参加比赛,现在给出你所有人的分数,小明 ...

  3. hdu 5312 dp(背包)、二分图或其他姿势

    题意:给出一个二分图(不一定连通),问最多能加多少边,使它仍然是二分图 BC周年庆第四题,貌似终判再终判之后数据还是有问题``` 据说貌似可以用bitset搞,而且姿势优美是正解```然而我还是用的d ...

  4. 一篇文章入门Jmeter性能测试【经典长文】

    孟船长  目录 1.性能测试定义2.为什么要做性能测试3.性能测试指标.性能测试分类4.Jmeter性能测试实战[入门级]5.参考文章链接 1.性能测试定义 百度&知乎 性能测试是通过自动化的 ...

  5. Dataframe 新增一列, apply 通用方法

    df['c'] = df.apply(lambda row: 1 if row['a'] < 0 and row['b'] > 0 else 0, axis=1) apply 是一个好方法 ...

  6. CentOS升级Python2.6到Python2.7并安装pip

    原文:http://ruter.sundaystart.net/2015/12/03/Update-python/ 貌似CentOS 6.X系统默认安装的Python都是2.6版本的?平时使用以及很多 ...

  7. ORACLE与SQL SERVER语法区别

    一.数据类型 ORACLE与SQL SERVER在数据类型的对比如下: SQL SERVER ORACLE 数字类型 DECIMAL[(P[, S])] NUMBER[(P[, S])] NUMERI ...

  8. Javascript undefined 和 null

    Javascript undefined 和 null 虽然 Javascript 一切皆对象,但是类型还是有区别的. undefined 表示 未定义的数据类型. null 表示空对象. 在判断时没 ...

  9. 【转】每天一个linux命令(13):less 命令

    原文网址:http://www.cnblogs.com/peida/archive/2012/11/05/2754477.html less 工具也是对文件或其它输出进行分页显示的工具,应该说是lin ...

  10. Excel的方向键失灵

    Excel的方向键操作不再是sheet范围内转动:而是变成了整个sheet页面在跳动. 不只是Excel,viso也是如此. 这是因为你的Scroll Lock键被按下了:所致箭头被解读为页面滚轮在滑 ...