《GPU高性能编程CUDA实战》附录一 高级原子操作
▶ 本章介绍了手动实现原子操作。重构了第五章向量点积的过程。核心是通过定义结构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实战》附录一 高级原子操作的更多相关文章
- [问题解决]《GPU高性能编程CUDA实战》中第4章Julia实例“显示器驱动已停止响应,并且已恢复”问题的解决方法
以下问题的出现及解决都基于"WIN7+CUDA7.5". 问题描述:当我编译运行<GPU高性能编程CUDA实战>中第4章所给Julia实例代码时,出现了显示器闪动的现象 ...
- 《GPU高性能编程CUDA实战》附录二 散列表
▶ 使用CPU和GPU分别实现散列表 ● CPU方法 #include <stdio.h> #include <time.h> #include "cuda_runt ...
- 《GPU高性能编程CUDA实战》附录四 其他头文件
▶ cpu_bitmap.h #ifndef __CPU_BITMAP_H__ #define __CPU_BITMAP_H__ #include "gl_helper.h" st ...
- 《GPU高性能编程CUDA实战》附录三 关于book.h
▶ 本书中用到的公用函数放到了头文件book.h中 #ifndef __BOOK_H__ #define __BOOK_H__ #include <stdio.h> #include &l ...
- 《GPU高性能编程CUDA实战》第十一章 多GPU系统的CUDA C
▶ 本章介绍了多设备胸膛下的 CUDA 编程,以及一些特殊存储类型对计算速度的影响 ● 显存和零拷贝内存的拷贝与计算对比 #include <stdio.h> #include " ...
- 《GPU高性能编程CUDA实战》第五章 线程并行
▶ 本章介绍了线程并行,并给出四个例子.长向量加法.波纹效果.点积和显示位图. ● 长向量加法(线程块并行 + 线程并行) #include <stdio.h> #include &quo ...
- 《GPU高性能编程CUDA实战》第四章 简单的线程块并行
▶ 本章介绍了线程块并行,并给出两个例子:长向量加法和绘制julia集. ● 长向量加法,中规中矩的GPU加法,包含申请内存和显存,赋值,显存传入,计算,显存传出,处理结果,清理内存和显存.用到了 t ...
- 《GPU高性能编程CUDA实战》第八章 图形互操作性
▶ OpenGL与DirectX,等待填坑. ● basic_interop #include <stdio.h> #include "cuda_runtime.h" ...
- 《GPU高性能编程CUDA实战》第七章 纹理内存
▶ 本章介绍了纹理内存的使用,并给出了热传导的两个个例子.分别使用了一维和二维纹理单元. ● 热传导(使用一维纹理) #include <stdio.h> #include "c ...
随机推荐
- 代理模式及Spring AOP (一)
一.代理模式 在不更改源码的前提下,加入新功能,通常需要用到代理设计模式. 代理设计模式分类: 静态代理 动态代理 jdk动态代理 cglib动态代理 其中spring AOP的底层用的是动态代理.其 ...
- 习题3.5 求链表的倒数第m个元素(20 分)浙大版《数据结构(第2版)》题目集
请设计时间和空间上都尽可能高效的算法,在不改变链表的前提下,求链式存储的线性表的倒数第m(>0)个元素. 函数接口定义: ElementType Find( List L, int m ); 其 ...
- git的使用方法学习
1.git常用命令: git stash: 备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致.同时,将当前的工作区内容保存到Git栈中. git stash p ...
- 看懂Class文件的装载流程
Class文件的加载过程 ClassLoader的工作模式 类的热加载 1 Class文件的装载流程 只有被java虚拟机装载的Class类型才能在程序中使用(注意装载和加载的区别) 1.1 类装载的 ...
- 寻找高边电流IC
因为项目需要,无法使用地的电流检测,需要使用高边的电流检测 IC. 搜索的关键字: 高边 电流 高侧 电流 目前找到以下几款: INA199A1,来自参考方案,属于宽电压输入的. INA180B4ID ...
- 从Vue文件到Html文件
如下图,通过webpack打包工具,将一个Vue文件生成html,css,js文件.其中js对应的是new Vue({})
- Angularjs 事件指令
1. 点击事件 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" ...
- mysql编译安装(详细)
一.编译安装MySQL前的准备工作 安装编译源码所需的工具和库 yum install gcc gcc-c++ ncurses-devel perl 安装cmake,从http://www.cmake ...
- DataSet和DataTable有用的方法
每一个DataSet都是一个或多个DataTable 对象的集合(DataTable相当于数据库中的表),这些对象由数据行(DataRow).数据列(DataColumn).字段名(Column Na ...
- linux 搭建 redis
找了很多教程总有一个适合我 http://www.cnblogs.com/_popc/p/3684835.html 当然我的目录是/opt/redis 文章中的目录是/usr/local/redi ...