《GPU高性能编程CUDA实战》第四章 简单的线程块并行
▶ 本章介绍了线程块并行,并给出两个例子:长向量加法和绘制julia集。
● 长向量加法,中规中矩的GPU加法,包含申请内存和显存,赋值,显存传入,计算,显存传出,处理结果,清理内存和显存。用到了 tid += gridDim.x; 使得线程块可以读取多个下标,计算长于线程块数量的向量(例子中向量长度为32768,线程块数量为1024)
#include <stdio.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "D:\Code\CUDA\book\common\book.h" #define N (32 * 1024) __global__ void add(int *a, int *b, int *c)
{
int tid = blockIdx.x;
while (tid < N)
{
c[tid] = a[tid] + b[tid];
tid += gridDim.x;
}
return;
} int main(void)
{
int *a, *b, *c;
int *dev_a, *dev_b, *dev_c; // 申请内存和显存
a = (int*)malloc(N * sizeof(int));
b = (int*)malloc(N * sizeof(int));
c = (int*)malloc(N * sizeof(int));
cudaMalloc((void**)&dev_a, N * sizeof(int));
cudaMalloc((void**)&dev_b, N * sizeof(int));
cudaMalloc((void**)&dev_c, N * sizeof(int)); // 数组填充
for (int i = ; i < N; i++)
{
a[i] = i;
b[i] = * i;
} // 将内存中的a和b拷贝给显存中的dev_a和dev_b
cudaMemcpy(dev_a, a, N * sizeof(int), cudaMemcpyHostToDevice);
cudaMemcpy(dev_b, b, N * sizeof(int), cudaMemcpyHostToDevice); // 调用核函数
add <<<, >>>(dev_a, dev_b, dev_c); // 将显存中的dev_c从显存拷贝回内存中的c
cudaMemcpy(c, dev_c, N * sizeof(int), cudaMemcpyDeviceToHost); // 检验结果
bool success = true;
for (int i = ; i<N; i++)
{
if ((a[i] + b[i]) != c[i])
{
printf("Error at i==%d:\n\t%d + %d != %d\n", i, a[i], b[i], c[i]);
success = false;
break;
}
}
if (success)
printf("We did it!\n"); // 释放内存和显存
free(a);
free(b);
free(c);
cudaFree(dev_a);
cudaFree(dev_b);
cudaFree(dev_c); getchar();
return ;
}
● 绘制Julia集:
#include <stdio.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "D:\Code\CUDA\book\common\book.h"
#include "D:\Code\CUDA\book\common\cpu_bitmap.h" #define DIM 1000 // 输出图形的边长
#define USE_CPU false // true使用CPU,false使用GPU struct DataBlock
{
unsigned char *dev_bitmap;
}; struct cuComplex// 自定义复数类型
{
float r;
float i;
__host__ __device__ cuComplex(float a, float b) : r(a), i(b) {}
__host__ __device__ float magnitude2(void)
{
return r * r + i * i;
}
__host__ __device__ cuComplex operator*(const cuComplex& a)
{
return cuComplex(r*a.r - i*a.i, i*a.r + r*a.i);
}
__host__ __device__ cuComplex operator+(const cuComplex& a)
{
return cuComplex(r + a.r, i + a.i);
}
}; __host__ __device__ int julia(int x, int y)// 判定一个点是否属于julia集
{
const float scale = 1.5;
float jx = scale * (float)(DIM / - x) / (DIM / );
float jy = scale * (float)(DIM / - y) / (DIM / ); cuComplex c(-0.8, 0.056);// 事先规定的偏移值
cuComplex a(jx, jy); int i = ;
for (i = ; i<; i++)
{
a = a * a + c;
if (a.magnitude2() > )
return ;
}
return ;
} void kernelCPU(unsigned char *ptr)// CPU中按循环遍历每个点进行判定
{
for (int y = ; y<DIM; y++)
{
for (int x = ; x<DIM; x++)
{
int offset = x + y * DIM;
int juliaValue = julia(x, y);
ptr[offset * + ] = * juliaValue;
ptr[offset * + ] = ;
ptr[offset * + ] = ;
ptr[offset * + ] = ;
}
}
return;
} __global__ void kernelGPU(unsigned char *ptr)// GPU中每个线程块判定一个点
{
int x = blockIdx.x;
int y = blockIdx.y;
int offset = x + y * gridDim.x; int juliaValue = julia(x, y);
ptr[offset * + ] = ;
ptr[offset * + ] = * juliaValue;
ptr[offset * + ] = ;
ptr[offset * + ] = ;
return;
} int main(void)
{
#if USE_CPU
CPUBitmap bitmap(DIM, DIM);
unsigned char *ptr = bitmap.get_ptr(); kernelCPU(ptr);
#else
DataBlock data;
CPUBitmap bitmap(DIM, DIM, &data);
unsigned char *dev_bitmap;
cudaMalloc((void**)&dev_bitmap, bitmap.image_size());
data.dev_bitmap = dev_bitmap; kernelGPU << < dim3(DIM, DIM), >> > (dev_bitmap); cudaMemcpy(bitmap.get_ptr(), dev_bitmap, bitmap.image_size(), cudaMemcpyDeviceToHost);
cudaFree(dev_bitmap);
#endif bitmap.display_and_exit();
printf("\n\tfinished!");
getchar();
return ;
}
▶ 在定义结构体的时候定义结构的运算 __host__ __device__ cuComplex(float a, float b) : r(a), i(b) {} ,表明初始化结构实例时可以传入两个浮点参数 a 和 b,并将它们分别当做该实例的两个分量。类似的情形在结构dim3中也有体现。
//在vector_types.h中预定义的结构dim3
struct __device_builtin__ dim3
{
unsigned int x, y, z;
#if defined(__cplusplus)
__host__ __device__ dim3(unsigned int vx = , unsigned int vy = , unsigned int vz = ) : x(vx), y(vy), z(vz) {}
__host__ __device__ dim3(uint3 v) : x(v.x), y(v.y), z(v.z) {}
__host__ __device__ operator uint3(void) { uint3 t; t.x = x; t.y = y; t.z = z; return t; }
#endif /* __cplusplus */
}; //然后在CUDA的代码中可以使用
dim3 threads = dim3(, );
dim3 blocks = dim3(n / threads.x, );
《GPU高性能编程CUDA实战》第四章 简单的线程块并行的更多相关文章
- 《GPU高性能编程CUDA实战》第九章 原子性
▶ 本章介绍了原子操作,给出了基于原子操作的直方图计算的例子. ● 章节代码 #include <stdio.h> #include "cuda_runtime.h" ...
- [问题解决]《GPU高性能编程CUDA实战》中第4章Julia实例“显示器驱动已停止响应,并且已恢复”问题的解决方法
以下问题的出现及解决都基于"WIN7+CUDA7.5". 问题描述:当我编译运行<GPU高性能编程CUDA实战>中第4章所给Julia实例代码时,出现了显示器闪动的现象 ...
- 《GPU高性能编程CUDA实战》第五章 线程并行
▶ 本章介绍了线程并行,并给出四个例子.长向量加法.波纹效果.点积和显示位图. ● 长向量加法(线程块并行 + 线程并行) #include <stdio.h> #include &quo ...
- 《GPU高性能编程CUDA实战中文》中第四章的julia实验
在整个过程中出现了各种问题,我先将我调试好的真个项目打包,提供下载. /* * Copyright 1993-2010 NVIDIA Corporation. All rights reserved. ...
- 《GPU高性能编程CUDA实战》第十一章 多GPU系统的CUDA C
▶ 本章介绍了多设备胸膛下的 CUDA 编程,以及一些特殊存储类型对计算速度的影响 ● 显存和零拷贝内存的拷贝与计算对比 #include <stdio.h> #include " ...
- 《GPU高性能编程CUDA实战》第七章 纹理内存
▶ 本章介绍了纹理内存的使用,并给出了热传导的两个个例子.分别使用了一维和二维纹理单元. ● 热传导(使用一维纹理) #include <stdio.h> #include "c ...
- 《GPU高性能编程CUDA实战》第六章 常量内存
▶ 本章介绍了常量内存的使用,并给光线追踪的一个例子.介绍了结构cudaEvent_t及其在计时方面的使用. ● 章节代码,大意是有SPHERES个球分布在原点附近,其球心坐标在每个坐标轴方向上分量绝 ...
- 《GPU高性能编程CUDA实战》第三章 CUDA设备相关
▶ 这章介绍了与CUDA设备相关的参数,并给出了了若干用于查询参数的函数. ● 代码(已合并) #include <stdio.h> #include "cuda_runtime ...
- 《GPU高性能编程CUDA实战》附录四 其他头文件
▶ cpu_bitmap.h #ifndef __CPU_BITMAP_H__ #define __CPU_BITMAP_H__ #include "gl_helper.h" st ...
随机推荐
- camera-arm-RPI
这个属于先收藏着,知道有个开源的东西. luvcview是一个开源项目,专注于UVC摄像头的测试,只要您的摄像头支持UVC驱动,即可使用luvcview测试程序,如何知道自己的摄像头是不是支持UVC驱 ...
- win10和ubuntu16.04双系统时间同步
在win10安装了ubuntu双系统,发现在两个系统见时间相差8个小时,这是由于windows和和ubuntu对于从主板取得时间后的处理方式不同,如果你把位置设为上海,ubuntu总是把主板时间当作u ...
- ALGO-22_蓝桥杯_算法训练_装箱问题(DP)
问题描述 有一个箱子容量为V(正整数,<=V<=),同时有n个物品(<n<=),每个物品有一个体积(正整数). 要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小. 输 ...
- C++进阶--Named Parameter Idiom
//############################################################################ /* Named Parameter Id ...
- WINDOWS和linux下stdcall
__stdcall被这个关键字修饰的函数,其参数都是从右向左通过堆栈传递的(__fastcall 的前面部分由ecx,edx传), 函数调用在返回前要由被调用者清理堆栈.这个关键字主要见于Micros ...
- 【IIS错误】IIS各种错误
IIS简介 当用户试图通过HTTP或文件传输协议(FTP)访问一台正在运行Internet信息服务 (IIS)的服务器上的内容时,IIS返回一个表示该请求的状态的数字代码.该状态代码 记录在IIS日志 ...
- js 取一个对象的长度,取出来的是undefined,自己写的一个计算长度的函数解决了。
收藏 牙膏儿 发表于 3年前 阅读 13085 收藏 7 点赞 1 评论 1 [粉丝福利]-<web 前端基础到实战系列课程>免费在线直播教学>>> 昨晚写一段代码, ...
- Java-Runoob-高级教程-实例-时间处理:03. Java 实例 - 获取年份、月份等
ylbtech-Java-Runoob-高级教程-实例-时间处理:03. Java 实例 - 获取年份.月份等 1.返回顶部 1. Java 实例 - 获取年份.月份等 Java 实例 以下实例演示 ...
- WebStrom配置SVN服务
本文讲解了如何在公司内网通过代理使用WebStrom等软件连接外部svn服务器,重点在于如何配置网络. 网络设置 1.配置WebStrom软件公司内网网络环境.首先配置代理服务器,点击“file-&g ...
- [转]Windows7:Visual Studio 2008试用版的评估期已经结束解决方法
原文来自:http://blog.sina.com.cn/s/blog_6b1815080100y5z3.html 以前在Windows2003碰到这个问题时,都是到"控制面板→添加 ...