CUDA从入门到精通到精通_笔记3:第一个CUDA程序及其代码详解

/*******************************************************************************************************************
*文件说明:
*        第一个CUDA程序-------核函数的调用
*开发环境:
*        win7+OpenCv2.4.8+cuda5.0+NIVIDA NVS 3100M
*时间地点:
*        陕西师范大学 2017.1.7
*作    者:
*        九月
********************************************************************************************************************/
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <iostream>
/*******************************************************************************************************************
*模块说明:
*        CUDA中,核函数的定义
*函数说明:
*        1--主机代码(Host Code)-------在CPU上运行的代码,成为【主机代码】
*        2--设备代码(Device Code)-----在GPU上运行的代码成为【设备代码】
*__global__修饰符的解释:
*        1--这个修饰符是CUDA C为标准C语言增加的【关键字修饰符】
*        2--这个修饰符将告诉编译器,这个函数应该被编译为在设备上运行的代码,而不应该被编译为在主机上运行的代码
*        3--在这个简单的例子中,函数kernel()将被交给编译设备代码的编译器进行编译,而main函数将被交给主机编译器编译
*        4--那么,kernel()函数的调用究竟代表什么含义,并且为什么必须加上尖括号和两个数值呢?注意,这正是使用CUDA的地方
*        5--我们已经看到,CUDA C需要通过某种语法标记的方法讲一个函数标记为【设备代码---Device Code】,这并没有什么特别
*           之处,而只是一种简单的表示方法
*        6--表示将【主机代码】发送到一个编译器,而将设备代码发送到另一个编译器
********************************************************************************************************************/
__global__ void kernel(void)
{
}
/*******************************************************************************************************************
*模块说明:
*        传递参数
*模块说明:
*        1--注意,这里增加了多行代码,在这些代码中,包含两个概念:
*              1--可以像调用【C函数】那样,将参数传递给【核函数】
*              2--当【设备】执行任何有用的操作是,都需要分配内存;例如:将计算值返回给【主机】
*              3--在将【参数】传递给【核函数】的过程中,没有任何的特别之处;除了【尖括号的语法】之外,【核函数】的外表
*                 和行为看上去和标准C语言中的任何函数的调用一样。【运行时系统】负责处理参数从【主机】传递给【设备】
*                 的过程中的所有复杂操作
*              4--更需要注意的地方在于通过调用cudaMalloc()来分配内存。这个函数的行为非常类似于标准C语言中的malloc
*                 函数,但cudaMalloc函数的作用是告诉【CUDA运行时】在【设备】上分配内存。
*malloc函数:
*    1--函数原型:void* malloc(size_t size)
*
******************************************************************************************************************/
/*******************************************************************************************************************
*malloc函数说明:
*函数原型:
*         void* malloc(size_t size)
*函数作用:
*         malloc函数用于分配一个指定大小的内存空间;如果分类成功,函数返回一个指向该内存空间起始地址的void类型的指针;
*         如果分配失败,函数返回0值指针NULL.
*函数参数:
*         参数size表示申请分配的字节数,类型size_t一般为unsigned int
*cudaMalloc函数说明:
*        __device__ __attribute__((nv_weak)) cudaError_t cudaMalloc(void **p, size_t s)
*函数作用:
*        在【设备】上分配s个字节的线性存储单元的存储空间,并且以*p的形式返回一个指向分配空间起始地址,有p是一个二级
*        指针,针对任何类型的变量,合理的调整所分配内存的空间。这个空间不会被清除,如果出现错误,cudaMalloc将会返回
*        cudaErrorMemoryAllocation
*需要注意的一点是:
*        1--程序员一定不能在【主机代码】中对cudaMalloc()返回的指针进行解引用Deference;
*        2--但是,【主机代码】可以将这个指针作为参数传递,对其执行算数运算,甚至可以将其转换为另一种不同的类型;
*        3--但是,绝对不可以使用这个指针来读取或者写入内存
*【设备指针】的使用限制如下所示:
*        1--可以将cudaMalloc函数分配的指针传递给设备上执行的函数
*        2--可以在【设备代码】中使用cudaMalloc分配的函数进行【内存的读写】
*        3--可以将cudaMalloc分配的指针传递给在主机上执行的函数
*        4--不能在主机代码中使用cudaMalloc分配的指针对【内存】进行读写
*代码说明:
*        1--通过上面的解释,我们已经看到了如何在【设备】上分配内存和释放内存,同时,也清楚的看到,在【主机】上不能对这
*           块内存做任何修改。
*        2--在示例程序中剩下来的两行代码给出了访问【设备内存】的两种最常见的方法:
*             1--在【设备代码】中使用设备内存
*             2--以及调用cudaMemcpy()
*        3--【设备指针】的使用方式与【标准C语言】中指针的使用方式完全一致。语句*c=a+b的含义同样非常简单,将参数a和b
*            相加,并将结果保存在c指向的内存中。
*注   意:
*        【主机指针】只能访问【主机代码】中的内存,而【设备指针】也只能访问【设备代码】中的【内存】
*C/C++中的【内存拷贝函数】函数说明:
*函数原型:
*        extern void *memcpy(void *dest, const void *src, size_t n)
*函数作用:
*        从源src指针所指向的起始地址位置拷贝n个字节的内容,拷贝到dest所指向的内存的起始地址位置
*cudaMemcpy函数说明:
*函数原型:
*extern __host__ cudaError_t CUDARTAPI cudaMemcpy(void *dst, const void *src, size_t count, enum cudaMemcpyKind kind);   
*函数参数:
*        enum cudaMemcpyKind kind---这个枚举类,有三个值:
*             1--cudaMemcpyDeviceToHost
*             2--cudaMemcpyHostToDevice
*             3--cudaMemcpyDeviceToDevice
*        这些参数都是用指定【设备指针】究竟是【源指针】还是【目标指针】
******************************************************************************************************************/
__global__ void add(int a,int b,int* c)
{
	*c =a+b;
}


/*******************************************************************************************************************
*模块说明:
*        控制台应用程序的入口函数----Main函数
********************************************************************************************************************/
int main(void)
{
	kernel<<<1,1>>>();
	printf("Hello CUDA!\n");

	int c = 0;
	int* dev_c = NULL;
	cudaMalloc((void**)&dev_c,sizeof(int));                 //【1】在设备内存中开辟n个字节的内存空间
	add<<<1,1>>>(3,7,dev_c);                                  //【2】调用【核函数】,并且在【设备代码】中使用【设备指针】
	cudaMemcpy(&c,dev_c,sizeof(int),cudaMemcpyDeviceToHost); //【3】将dev_c所指内存的起始地址位置的n个字节的内容拷贝到c所指针的内存中
	printf("3+7 = %d\n",c);
	cudaFree(dev_c);                                          //【4】释放在【设备】中开辟的【内存空间】

    std::system("pause");
	return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值