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

● 章节代码

 #include <stdio.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "cuda.h"
#include "D:\Code\CUDA\book\common\book.h" #define imin(a,b) (a<b?a:b)
#define sum_squares(x) (x*(x+1)*(2*x+1)/6)
#define N 33 * 1024 * 1024
#define THREADSIZE 256
#define BLOCKSIZE imin(32, (N + THREADSIZE - 1) / THREADSIZE) struct Lock
{
int *mutex;
Lock(void)
{
int state = ;
cudaMalloc((void **)&mutex, sizeof(int));
cudaMemcpy(mutex, &state, sizeof(int), cudaMemcpyHostToDevice);
}
~Lock(void)
{
cudaFree(mutex);
}
__device__ void lock(void)
{
while (atomicCAS(mutex, , ) != );
//atomicCAS(a, b, c)将判断变量a是否等于b,
//若相等,则用c的值去替换a,并返回c的值;若不相等,则返回a的值
//函数lock()中,线程不断尝试判断mutex是否为0,
//若为0则改写为1 ,表明“占用”,禁止其他线程进行访问
//若为1则继续尝试判断
}
__device__ void unlock(void)
{
atomicExch(mutex, );
//atomicExch(a, b)返回第一个变量的值,并将两个变量的值进行交换
//这里使用原子操作只是与上面的atomicCAS统一,否则可以直接用赋值语句
//线程操作完成,将mutex改写回0,允许其他线程进行访问
}
}; __global__ void dot(Lock lock, float *a, float *b, float *c)
{
__shared__ float share[THREADSIZE];
int tid = threadIdx.x + blockIdx.x * blockDim.x;
int cacheIndex = threadIdx.x;
float temp = ; while (tid < N)
{
temp += a[tid] * b[tid];
tid += blockDim.x * gridDim.x;
} share[cacheIndex] = temp;
__syncthreads(); int i = blockDim.x / ;
while (i != )
{
if (cacheIndex < i)
share[cacheIndex] += share[cacheIndex + i];
__syncthreads();
i /= ;
}
if (cacheIndex == )
{
lock.lock();// 等待可写入的机会,锁上,写入,再解锁
*c += share[];
lock.unlock();
}
} int main(void)
{
float *a, *b, c = ;
float *dev_a, *dev_b, *dev_c; a = (float*)malloc(N * sizeof(float));
b = (float*)malloc(N * sizeof(float)); cudaMalloc((void**)&dev_a, N * sizeof(float));
cudaMalloc((void**)&dev_b, N * sizeof(float));
cudaMalloc((void**)&dev_c, sizeof(float)); for (int i = ; i < N; i++)
{
a[i] = i;
b[i] = i * ;
} cudaMemcpy(dev_a, a, N * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(dev_b, b, N * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(dev_c, &c, sizeof(float), cudaMemcpyHostToDevice); Lock lock;
dot << <BLOCKSIZE, THREADSIZE >> > (lock, dev_a, dev_b, dev_c); cudaMemcpy(&c, dev_c, sizeof(float), cudaMemcpyDeviceToHost); printf("\n\tAnswer:\t\t%.6g\n\tGPU value:\t%.6g\n", * sum_squares((float)(N - )), c); free(a);
free(b);
cudaFree(dev_a);
cudaFree(dev_b);
cudaFree(dev_c);
getchar();
return ;
}

《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. C# 处理DateTime算法,取某月第1天及最后一天

    代码如下所示: /// <summary> /// 取得某月的第一天 /// </summary> /// <param name="datetime" ...

  2. java8 array、list操作 汇【3】)(-Java8新特性之Collectors 详解

    //编写一个定制的收集器 public static class MultisetCollector<T> implements Collector<T, Multiset<T ...

  3. Linux下软件包安装

    编译dbus下载地址 :http://dbus.freedesktop.org/releases/dbus/tar zxvf dbus-1.10.0echo ac_cv_have_abstract_s ...

  4. 比jsonpath 更方便的json 数据查询JMESPath 使用

      类似xml 的xpath json 有jsonpath 都是为了方便进行数据查询,但是jsonpath 的功能 并不是很强大,如果为了方便查询可以使用jmespath. 以下为简单使用: 查询格式 ...

  5. Python包管理工具easy_install使用

    easy_install是python的包管理工具,可以方便的下载.安装.更新python包,并可以自动处理相关依赖.类似于ruby的gem,java的maven,nodejs的npm. 安装方法有两 ...

  6. php过滤html标签截取部分内容

    <?php $str = '<span>fdsfsdf</span><a href="#">href</a>'; echo h ...

  7. curl 知识点

    curl :command line tool and library for transferring data with URLs curl 命令,常用缩写: curl 命令 缩写 说明 curl ...

  8. http 301 和 302的区别

    301 永久重定向 301 重定向是当用户或搜索引擎向网站服务器发出浏览请求时,服务器返回的HTTP数据流中头信息(header)中的状态码的一种,表示本网页永久性转移到另一个地址. 301 重定向是 ...

  9. WIN7\win10下使用批处理配置JAVA环境变量

    我找了很多环境变量批处理的教程,都不太满意,因此综合修改了下,拼凑出了这么一个版本. 下面这个是我主要参考的博客,大部分的代码都是来自这里: http://blog.csdn.net/lpy36543 ...

  10. Angular 4 路由守卫

    路由守卫 只有当用户已经登录并拥有某些权限时才能进入某些路由 一个有多个表单组成的向导,如注册流程,用户只有在当前组件的组件中填写了满足要求的信息才可以导航到下一个路由 当用户未执行保存操作而试图离开 ...