转自:http://blog.sina.com.cn/s/blog_48b9e1f90100fm56.html

CUDA的代码分成两部分,一部分在host(CPU)上运行,是普通的C代码;另一部分在device(GPU)上运行,是并行代码,称为kernel,由nvcc进行编译。

Kernel产生的所有线程成为Grid。在并行部分结束后,程序回到串行部分即到host上运行。

在CUDA中,host和device有不同的内存空间。所以在device上执行kernel时,程序员需要把host memory上的数据传送到分配的device memory上。在device执行完以后,需要把结果从device传送回host,并释放device memory。CUDA runtime system提供了API给程序员做这些事情。

Float *Md;

Int size=Width*Width*sizeof(float);

API:

cudaMalloc((void**)&Md, size)——从host code调用,为device在global memory分配内存空间。第一个参数是指向分配对象的地址,第二个参数是分配大小;

cudaFree(Md)——释放device Global Memory。

cudaMemcpy(Md, M, size, dudaMemcpyHostToDevice)——内存数据传输。四个参数分别为:指向目的数据的指针,指向源(要copy的)数据指针,要copy出的数据字节数,传输方式(host to host, host to device, device to host, device to device)

内核部分

__global__说明这个函数是一个kernel,host function可以调用这个函数产生线程

threadIdx.x线程index

一个kernel被调用时,以并行线程的grid形式执行。一个kernel创建一个grid。Grid中的线程被组织成两个层次。在最顶层,每个grid包含一个或多个thread block。Grid中的所有block有相同数目的线程。每个thread block有一个唯一的二维坐标,由CUDA的特定关键字blockIdx.x和blockIdx.y指定。所有的thread block必须以相同的方式组织,并有相同数目的thread。

Thread block:包含相互之间能够协作的线程,这些线程通过同步或者在低延迟的shared memory之间共享数据进行协作。不同block里的线程不能协作。每个thread block组织成三位的线程数组,最大线程数目为512。Block中的线程坐标是唯一的,通过三个线程id指定:threadIdx.x, threadIdx.y, threadIdx.z。不是所有的应用程序会使用thread block的三个维度。

当host code调用一个kernel时,通过参数传递来设置grid和thread block的维度。如下:

// Setup the execution configuration

dim3 dimBlock(WIDTH, WIDTH);

dim3 dimGrid(1, 1);

// Launch the device computation threads!

MatrixMulKernel<<<dimGrid, dimBlock>>>(Md, Nd, Pd);

以上是摘自David Kirk和Wen-mei Hwu的课程,讲的比较清楚。感觉CUDA编程一个比较自由的编程方式,由于是在C之上的扩展,加了一些关键字,比较容易,编程方式让人很好接受。一方面给了程序员很大的发挥空间,thread, thread block等都可以自由配置,另一方面也给程序员提出了挑战,这么大的空间中怎样编程以取得好的性能。

一个简单的矩阵乘程序

#include<stdio.h>

#include<stdlib.h>

#include<cuda.h>

//内核程序

__global__ void MatrixMulKernel(float* Md, float* Nd, float* Pd, int Width)

{

//2D Thread ID

int tx=threadIdx.x;

int ty=threadIdx.y;

printf("I'm thread: %d %d\n",tx,ty);

//Pvalue stores the Pd element that is computed by the thread

float Pvalue=0;

for(int k=0; k<Width; k++)

{

float Mdelement=Md[ty*Width+k];

float Ndelement=Nd[k*Width+tx];

Pvalue+=Mdelement*Ndelement;

printf("%f  %f   %f\n",Mdelement,Ndelement,Pvalue);

}

//Write the matrix to device memory each thread writes one element

Pd[ty*Width+tx]=Pvalue;

}

void MatrixMulOnDevice(float* M, float* N, float* P, int Width)

{

int size=Width*Width*sizeof(float);

float *Md,*Nd,*Pd;

dim3 dimBlock(Width,Width);

dim3 dimGrid(1,1);

//Load M and N to device memory

cudaMalloc((void **)&Md,size);

cudaMemcpy(Md,M,size,cudaMemcpyHostToDevice);

cudaMalloc((void **)&Nd,size);

cudaMemcpy(Nd,N,size,cudaMemcpyHostToDevice);

//for(int i=0;i<3;i++)printf("%d ",Md[i]);

//Allocate P on the device

cudaMalloc((void**)&Pd,size);

//Kernel invocation code

MatrixMulKernel<<<dimGrid,dimBlock>>>(Md,Nd,Pd,Width);

//Read P from the device

cudaMemcpy(P,Pd,size,cudaMemcpyDeviceToHost);

//Free device matrices

cudaFree(Md);cudaFree(Nd);cudaFree(Pd);

}

int main(void)

{

// Allocate and initialize the matrices M,N,P

// I/O to read the input matrices M and N

//int size=Width*Width*sizeof(float);

float *M,*N,*P;

int Width=4;

//int size=Width*Width*sizeof(float);

int i=0;

M=(float *)malloc(sizeof(float)*Width*Width);

N=(float *)malloc(sizeof(float)*Width*Width);

P=(float *)malloc(sizeof(float)*Width*Width);

for(i=0;i<Width*Width;i++)

M[i]=(float)i;

for(i=0;i<Width*Width;i++)

N[i]=(float)i;

//      for(i=0;i<Width*Width;i++)

//              printf("%3f  ",N[i]);

// M*N on the device

MatrixMulOnDevice(M,N,P,Width);

for(i=0;i<Width*Width;i++)

{

if(i%Width==0)printf("\n");

printf("%3f   ",P[i]);

}

printf("\n");

// I/O to write the output matrix P

// Free matrices M, N, P

free(M);free(N);free(P);

return 0;

}

运行命令:

nvcc -deviceemu matrixmul.cu -o matrixmul

注意: -deviceemu在此处是必须的,因为在device中调用了printf,这属于device调用了host function

下一步:理解计算是怎样并行的?

普通CPU程序和GPU程序的性能比怎样?用时间衡量

CUDA学习笔记(一)——CUDA编程模型的更多相关文章

  1. CUDA学习笔记-1: CUDA编程概览

    1.GPU编程模型及基本步骤 cuda程序的基本步骤如下: 在cpu中初始化数据 将输入transfer到GPU中 利用分配好的grid和block启动kernel函数 将计算结果transfer到C ...

  2. 大数据学习笔记3 - 并行编程模型MapReduce

    分布式并行编程用于解决大规模数据的高效处理问题.分布式程序运行在大规模计算机集群上,集群中计算机并行执行大规模数据处理任务,从而获得海量计算能力. MapReduce是一种并行编程模型,用于大规模数据 ...

  3. 孙鑫VC学习笔记:多线程编程

    孙鑫VC学习笔记:多线程编程 SkySeraph Dec 11st 2010  HQU Email:zgzhaobo@gmail.com    QQ:452728574 Latest Modified ...

  4. Hadoop学习笔记(7) ——高级编程

    Hadoop学习笔记(7) ——高级编程 从前面的学习中,我们了解到了MapReduce整个过程需要经过以下几个步骤: 1.输入(input):将输入数据分成一个个split,并将split进一步拆成 ...

  5. WCF学习笔记之事务编程

    WCF学习笔记之事务编程 一:WCF事务设置 事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元: WCF通过System.ServiceModel.TransactionFlowA ...

  6. Java并发编程的艺术读书笔记(2)-并发编程模型

    title: Java并发编程的艺术读书笔记(2)-并发编程模型 date: 2017-05-05 23:37:20 tags: ['多线程','并发'] categories: 读书笔记 --- 1 ...

  7. ArcGIS案例学习笔记-批量裁剪地理模型

    ArcGIS案例学习笔记-批量裁剪地理模型 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 功能:空间数据的批量裁剪 优点:1.批量裁剪:任意多个目标数据,去裁剪任意 ...

  8. java学习笔记15--多线程编程基础2

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note15.html,转载请注明源地址. 线程的生命周期 1.线程的生命周期 线程从产生到消亡 ...

  9. Java学习笔记之---单例模型

    Java学习笔记之---单例模型 单例模型分为:饿汉式,懒汉式 (一)要点 1.某个类只能有一个实例 2.必须自行创建实例 3.必须自行向整个系统提供这个实例 (二)实现 1.只提供私有的构造方法 2 ...

  10. WebGL three.js学习笔记 加载外部模型以及Tween.js动画

    WebGL three.js学习笔记 加载外部模型以及Tween.js动画 本文的程序实现了加载外部stl格式的模型,以及学习了如何把加载的模型变为一个粒子系统,并使用Tween.js对该粒子系统进行 ...

随机推荐

  1. 连通性2 无向图的割边 (cut edge)

    这是DFS系列的第二篇 割边的概念 In graph theory, a bridge, isthmus, cut-edge, or cut arc is an edge of a graph who ...

  2. Shell编程检测监控mysql的CPU占用率

    shell编程很强大! 网站访问量大的时候mysql的压力就比较大,当mysql的CPU利用率超过300%的时候就不能提供服务了,近乎卡死状态,这时候最好的方法就是重启mysql服务.由于这种事具有不 ...

  3. Visual Studio Online Integrations-Sync and migration

      原文:http://www.visualstudio.com/zh-cn/explore/vso-integrations-directory-vs

  4. 运用加密技术保护Java源代码/定制ClassLoader

    为什么要加密? 对于传统的C或C++之类的语言来说,要在Web上保护源代码是很容易的,只要不发布它就可以.遗憾的是,Java程序的源代码很容易被别人偷看.只要有一个反编译器,任何人都可以分析别人的代码 ...

  5. LiLinux系统下如何修改主机名

    1,用root用户登录,或者切换root用户,先查看当前的主机名:hostname  (如果之前没有修改过,一般默认为localhost.localdomain): 2,vi /etc/sysconf ...

  6. Android内核开发:系统启动速度优化-Android OS启动优化(转)

    Android系统的启动优化主要分为三大部分: (1) Bootloader优化 (2) Linux Kernel的剪裁与优化 (3) Android OS部分的剪裁与优化 本文重点关注Android ...

  7. PyOpenGL利用文泉驿正黑字体显示中文字体

    摘要:在NeHe的OpenGL教程第43课源代码基础上,调用文泉驿正黑字体实现中文字体的显示 在OpenGL中显示汉字一直是个麻烦的事情,很多中文书籍的文抄公乐此不疲地介绍各种方法及其在windows ...

  8. 没玩过这些微信小游戏你就out了

    你确定没玩过下面这些微信小游戏?是不是有点out了?赶紧添加微信号kangfuyk,回复H5马上畅玩! 当然了,扫一下二维码关注后回复H5更快捷噢! 微信小游戏列表,持续更新中 辨色大比拼!心理游戏 ...

  9. cocos基础教程(11)事件分发机制

    cocos3.0的事件分发机制: 创建一个事件监听器-用来实现各种触发后的逻辑. 事件监听器添加到事件分发器_eventDispatcher,所有事件监听器有这个分发器统一管理. 事件监听器有以下几种 ...

  10. FineUI第七天---文件上传

       文件上传的方式: 控件的一些常用属性: ButtonText:按钮文本. ButtonOnly:是否只显示按钮,不显示只读输入框. ButtonIcon:按钮图标. ButtonIconUrl: ...