▶ 本章介绍了原子操作,给出了基于原子操作的直方图计算的例子。

● 章节代码

 #include <stdio.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "D:\Code\CUDA\book\common\book.h" #define SIZE (100*1024*1024)
#define USE_SHARE_MEMORY true __global__ void histo_kernel(unsigned char *buffer, long size, unsigned int *histo)
{
int i = threadIdx.x + blockIdx.x * blockDim.x; #if USE_SHARE_MEMORY
__shared__ unsigned int temp[];
temp[threadIdx.x] = ;
__syncthreads(); while (i < size)
{
atomicAdd(&temp[buffer[i]], );
i += blockDim.x * gridDim.x;
}
__syncthreads();
atomicAdd(&(histo[threadIdx.x]), temp[threadIdx.x]);
#else
while (i < size)
{
atomicAdd(&histo[buffer[i]], );
i += blockDim.x * gridDim.x;;
}
#endif
return;
} int main(void)
{
int i;
unsigned char *buffer = (unsigned char*)big_random_block(SIZE);// 内置的生成随机字符数组的函数 cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start, ); unsigned char *dev_buffer;
unsigned int *dev_histo;
cudaMalloc((void**)&dev_buffer, SIZE);
cudaMemcpy(dev_buffer, buffer, SIZE, cudaMemcpyHostToDevice); cudaMalloc((void**)&dev_histo, * sizeof(int));
cudaMemset(dev_histo, , * sizeof(int)); cudaDeviceProp prop;
cudaGetDeviceProperties(&prop, );
int blocks = prop.multiProcessorCount;// 书:实验表明使用MPS的两倍计算效率最高
histo_kernel << <blocks * , >> >(dev_buffer, SIZE, dev_histo); unsigned int histo[];
cudaMemcpy(histo, dev_histo, * sizeof(int), cudaMemcpyDeviceToHost); cudaEventRecord(stop, );
cudaEventSynchronize(stop);
float elapsedTime;
cudaEventElapsedTime(&elapsedTime, start, stop);
printf("Time to generate: %3.1f ms\n", elapsedTime); long histoCount = ;
for (i = ; i < ; i++)
histoCount += histo[i];
printf("Histogram Sum: %ld\n", histoCount); for (i = ; i < SIZE; i++)// 验证结果
histo[buffer[i]]--;
for (i = ; i < ; i++)
{
if (histo[i] != )
printf("Failure at hist[%d] == %d\n", i,histo[i]);
}
if (i == )
printf("\n\tSucceeded!\n"); cudaFree(dev_histo);
cudaFree(dev_buffer);
free(buffer);
cudaEventDestroy(start);
cudaEventDestroy(stop); getchar();
return ;
}

● 使用全局内存时,只要在每次线程尝试 +1 时使用原子加法即可;使用共享内存时算法分两步,线程先用原子加法往各线程块的共享内存中写入,同步以后,再用原子加法把各共享内存的结果往全局内存中写入。减缓了全局内存的写入冲突。

● 代码使用了两倍数量的MPS作为线程块数量,认为这样计算效率最高。在 GTX1070 上 prop.multiProcesser 为 16,程序默认使用 32 个线程块进行计算,我另用 1 到 256 个线程块依次测试,结果如下。

● big_random_block()定义于book.h中

 void* big_random_block(int size)
{
unsigned char *data = (unsigned char*)malloc(size);
for (int i = ; i < size; i++)
data[i] = rand();
return data;
}

《GPU高性能编程CUDA实战》第九章 原子性的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. 《GPU高性能编程CUDA实战》第六章 常量内存

    ▶ 本章介绍了常量内存的使用,并给光线追踪的一个例子.介绍了结构cudaEvent_t及其在计时方面的使用. ● 章节代码,大意是有SPHERES个球分布在原点附近,其球心坐标在每个坐标轴方向上分量绝 ...

  7. 《GPU高性能编程CUDA实战》第三章 CUDA设备相关

    ▶ 这章介绍了与CUDA设备相关的参数,并给出了了若干用于查询参数的函数. ● 代码(已合并) #include <stdio.h> #include "cuda_runtime ...

  8. 《GPU高性能编程CUDA实战中文》中第四章的julia实验

    在整个过程中出现了各种问题,我先将我调试好的真个项目打包,提供下载. /* * Copyright 1993-2010 NVIDIA Corporation. All rights reserved. ...

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

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

随机推荐

  1. 原生JS 的cookie和jq的cookie,

    COOKIE基础及应用:1.什么是COOKIE==>页面用来保存信息,比如:自动登录,记住用户名2.COOKIE的特性:  --同一个网站中,所有的页面共享同一套cookie  --数量,大小有 ...

  2. egret游戏入门之学习资源篇

    最近因需要,入手H5游戏. 写游戏当然需要有引擎. H5游戏开发:游戏引擎入门推荐 如何选择 H5 游戏引擎 白鹭引擎和layabox哪个好用,哪个技术更成熟 ? LayaBox 与 Egret 选择 ...

  3. 在windows下制作mac os x的启动安装U盘

    前几天有幸用了下Macbook pro,可在给它装win 7系统时,无知而又手贱地在windows系统下分区了:( 然后再重启就找不到Mac os x,只有win 7了.可进win 7也不正常,直接给 ...

  4. Java中的内存泄露

  5. Hadoop操作前准备工作

    摘要:本文介绍Hadoop操作前的准备工作. 关键词:Hadoop  Linux   JDK  WinSCP 俗语说,“磨刀不误砍柴工”.Hadoop操作前的准备工作可以加快Hadoop的操作与应用. ...

  6. grandstack 基于graphql&&react&& apollo&& neo4j 的全栈开发工具

    grandstack是一个基于graphql&&react&& apollo&& neo4j 的全栈开发工具. 有篇关于graphql 的5个常见问题的 ...

  7. oracle之 redo过高诊断

    一.诊断过度redo 要找到生成大量重做的会话,您可以使用以下任何一种方法.这两种方法都检查生成的撤销量.当一个事务生成撤销,它将自动生成重做. 当需要检查生成大量的程序时,使用第一个查询.当这些程序 ...

  8. css 通用兄弟选择器( ~ )

    stylus设置兄弟元素样式: 鼠标浮动在 .video-li 元素上时,.video-li 兄弟中 .video-info 下的 .word 显示. .video-li &:hover ~ ...

  9. 温习《PHP 核心技术与最佳实践》这本书

    再次看这本书,顺手提炼了一下大致目录,以便后续看见目录就知道大概讲的些什么内容 PHP 核心技术与最佳实践 1.面向对象思想的核心概念 1.1 面向对象的『形』与『本』 1.2 魔术方法的应用 1.2 ...

  10. 【FusionCharts学习-2】第一个FusionCharts程序

    获取资源 到官网:http://www.fusioncharts.com/download/ 获取FusionCharts文件: 目录结构: js目录下的文件: 创建项目 1. 项目名称:Fusion ...