▶ 本章介绍了线程块并行,并给出两个例子:长向量加法和绘制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实战》第四章 简单的线程块并行的更多相关文章

  1. 《GPU高性能编程CUDA实战》第九章 原子性

    ▶ 本章介绍了原子操作,给出了基于原子操作的直方图计算的例子. ● 章节代码 #include <stdio.h> #include "cuda_runtime.h" ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 宝塔linux面板运行jsp文件的配置工作

    第一步宝塔安装和软件安装我们先安装宝塔面板(这个不需要我说咋弄吧) 安装完成后登录到宝塔面板然后安装软件我个人喜欢nginx最新版,mysql由于服务器配置很菜所以没发装56,php什么的我用不到就没 ...

  2. 机器学习-Python中训练模型的保存和再使用

    模型保存 BP:model.save(save_dir) SVM: from sklearn.externals import joblib joblib.dump(clf, save_dir) 模型 ...

  3. 关于Eclipse无法显示package Explorer 内容的解决方法

    今天电脑不知道怎么搞的抽风了, package explorer等内容完全无法显示.用window->view方法手动添加还是setpreView都没有办法解决. 网上搜了半天也没有解决办法.无 ...

  4. MIME Types - Complete List

    Suffixes applicable Media type and subtype(s) .3dm x-world/x-3dmf .3dmf x-world/x-3dmf .a applicatio ...

  5. H5移动端开发vue+vux

    项目src中用到的npm包有(从编译打包到最终部署仍不能移除)1:vue             渐进式 JavaScript 框架   http://cn.vuejs.org/v2/guide/2: ...

  6. [UE4]旋转小地图

    一.Canvas Panel的旋转原点是Render Transform——>Pivot,Pivot坐标的取值范围是0到1,左上角的pivot坐标是[0,0],右下角的pivot坐标是[1,1] ...

  7. C# webbrowser如何获取滚动条的位置?

    获取滚动条的位置:  HtmlDocument document = WB1.Document; int top = document.GetElementsByTagName("HTML& ...

  8. Hadoop Api 基本操作

     hadoop环境配置好后,直接可以在window上进行调试.话不多说,直接上源码. package cn.terry; import java.io.FileInputStream; import ...

  9. RabbitMQ install (Ubuntu)

    1. key 1) Online way apt-key adv --keyserver "hkps.pool.sks-keyservers.net" --recv-keys &q ...

  10. Django中的跨表查询,多表查询。

    一:Django中的ORM进行操作. 必须掌握的十三条: <1> all(): 查询所有结果 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 & ...