## 一维矩阵的加

//实现一个一维1*16的小矩阵的加法。

//矩阵大小:1*16 

//分配一个block,共有16个线程并发。 

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#include <cuda_runtime.h>

#include <cutil.h>

#define VEC_SIZE 16

//kernel function 

__global__ void vecAdd(float* d_A,float* d_B,float* d_C) 



    int index=threadIdx.x; 

    d_C[index]=d_A[index]+d_B[index];

}

int main() 



    //得到分配空间的大小 

    size_t size=VEC_SIZE*sizeof(float);

//为本地分配内存 

    float* h_A=(float*)malloc(size); 

    float* h_B=(float*)malloc(size); 

    float* h_C=(float*)malloc(size);

//初始化 

    for (int i=0;i<VEC_SIZE;++i)   

   { 

        h_A[i]=1.0; 

        h_B[i]=2.0;  

    }

//将本地内存的中的数据复制到设备中 

    float* d_A; 

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

    cudaMemcpy(d_A,h_A,size,cudaMemcpyHostToDevice);

float* d_B; 

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

    cudaMemcpy(d_B,h_B,size,cudaMemcpyHostToDevice);

//分配存放结果的空间 

    float* d_C; 

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

//定义16个线程 

    dim3 dimblock(16); 

    vecAdd<<<1,dimblock>>>(d_A,d_B,d_C);

//讲计算结果复制回主存中 

    cudaMemcpy(h_C,d_C,size,cudaMemcpyDeviceToHost);

//输出计算结果 

    for (int j=0;j<VEC_SIZE;++j)    

   { 

        printf("%f/t",h_C[j]); 

    }

//释放主机和设备内存 

    cudaFree(d_A); 

    cudaFree(d_B); 

    cudaFree(d_C);

free(h_A); 

    free(h_B); 

    free(h_C);

return 0; 

}

## cudaMallocPitch()的使用

名称 cudaMallocPitch – 向GPU分配存储器

概要 cudaError_t cudaMallocPitch( void** devPtr,size_t* pitch,size_t widthInBytes,size_t height )

说明 向设备分配至少widthInBytes*height字节的线性存储器,并以*devPtr的形式返回指向所分配存储器的指针。该函数可以填充所分配的存储器,以确保在地址从一行更新到另一行时,给定行的对应指针依然满足对齐要求。cudaMallocPitch()以*pitch的形式返回间距,即所分配存储器的宽度,以字节为单位。间距用作存储器分配的一个独立参数,用于在2D数组内计算地址。如果给定一个T类型数组元素的行和列,可按如下方法计算地址:

T* pElement = (T*)((char*)BaseAddress + Row * pitch) + Column;

对于2D数组的分配,建议程序员考虑使用cudaMallocPitch()来执行间距分配。由于硬件中存在间距对齐限制,如果应用程序将在设备存储器的不同区域之间执行2D存储器复制(无论是线性存储器还是CUDA数组),这种方法将非常有用。

例子:为EmuDebug 

原来《CUDA编程指南》上给出的pitch的类型为int,在实际运行时与cudaMallocPitch()类型不匹配。

/************************************************************************/

/*  This is a example of the CUDA program. 

/************************************************************************/

#include <stdio.h>

#include <stdlib.h>

#include <cuda_runtime.h>

#include <cutil.h>

/************************************************************************/ 

/* myKernel                                                           */ 

/************************************************************************/ 

__global__ void myKernel(float* devPtr,int height,int width,int pitch) 



    for(int r=0;r    { 

        float* row=(float*)((char*)devPtr+r*pitch); 

        for (int c=0;c        { 

            float element=row[c]; 

            printf("%f/n",element);//模拟运行 

        } 

    } 

}

/************************************************************************/ 

/* Main CUDA                                                            */ 

/************************************************************************/ 

int main(int argc, char* argv[]) 



    size_t width=10; 

    size_t height=10; 

    float* decPtr; 

   //pitch的值应该为size_t在整形的时,与函数参数不匹配 

    size_t pitch; 

    cudaMallocPitch((void**)&decPtr,&pitch,width*sizeof(float),height);  

    myKernel<<<1,1>>>(decPtr,10,10,pitch); 

    cudaFree(decPtr);

printf("%d/n",pitch);

//CUT_EXIT(argc, argv);

return 0; 

}

## cudaMallocArray()的使用

名称: 
cudaMemcpyToArray – 在主机和设备间复制数据

概要: 
cudaError_t cudaMemcpyToArray(struct cudaArray* dstArray,size_t dstX,size_t dstY,const void* src,size_t count,enum cudaMemcpyKind kind) 

cudaError_t cudaMemcpyToArrayAsync(struct cudaArray* dstArray,size_t dstX,size_t dstY,const void* src,size_t count,enum cudaMemcpyKind kind,cudaStream_t stream)

说明 
从src指向的存储器区域内将count个字节复制到一个CUDA数组dstArray,该数组的左上角从(dstX,dstY)开始,其中kind是cudaMemcpyHostToHost、cudaMemcpyHost-ToDevice、cudaMemcpyDeviceToHost或cudaMemcpyDeviceToDevice之一,用于指定复制的方向。 

cudaMemcpyToArrayAsync()是异步的,可选择传入非零流参数,从而将其关联到一个流。它仅对分页锁定的主存储器有效,如果传入指向可分页存储器的指针,那么将返回一个错误。

返回值 
相关返回值: 

cudaSuccess 

cudaErrorInvalidValue 

cudaErrorInvalidDevicePointer cudaErrorInvalidMemcpyDirection 

注意,如果之前是异步启动,该函数可能返回错误码。

注: 

在《CUDA编程指导》中对,cudaMallocArray()函数的使用,个人觉得有错误。 

enum cudaMemcpyKind kind ,应该是cudaMemcpyHostToHost、cudaMemcpyHost-ToDevice、cudaMemcpyDeviceToHost或cudaMemcpyDeviceToDevice之一。 

在指导中使用的是cudaMemcpyToArray(cuArray,0,0,h_data,&channelDesc),channelDese为cudaChannelFormatDesc类型,不是cudaMemcpyKind.

/*********************************************************************/ 

/*  This is a example of the CUDA program.*/ 

/*********************************************************************/ 

#include <stdio.h>

#include <stdlib.h>

#include <cuda_runtime.h>

#include <cutil.h>

/************************************************************************/ 

/* myKernel                                                           */ 

/************************************************************************/ 

/************************************************************************/ 

/* Main CUDA                                                            */ 

/************************************************************************/ 

int main(int argc, char* argv[]) 



    const int width=10; 

    const int height=10;

//初始化h_array  

   int h_array[width][height]; 

    for (int i=0;i<width;i++)

        for (int j=0;j<height;++j)

            h_array[i][j]=j+i*64; 

        } 

    }

//以机构提channelDesc描述CUDA数组中的组件数量和数据类型 

    cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(32,0,0,0,cudaChannelFormatKindUnsigned); 

    cudaArray* cuArray; 

    cudaMallocArray(&cuArray,&channelDesc,width,height); 

     

    size_t sizeMem=width*height*sizeof(int); 

    size_t potX=0; 

    size_t potY=0; 

    cudaMemcpyToArray(cuArray,potX,potY,h_array,sizeMem,cudaMemcpyDeviceToHost);

cudaFreeArray(cuArray);

return 0; 

}

## CUDA统计时间

在CUDA中统计运算时间,大致有三种方法:

<1>使用cutil.h中的函数

unsigned int timer=0;

//创建计时器

cutCreateTimer(&timer);

//开始计时

cutStartTimer(timer);

{

  //统计的代码段

  …………

}

//停止计时

cutStopTimer(timer);

//获得从开始计时到停止之间的时间

cutGetTimerValue( timer);

//删除timer值

cutDeleteTimer( timer);

不知道在这种情况下,统计精度。

<2>time.h中的clock函数

clock_t start, finish;

float costtime;

start = clock(); 

{

  //统计的代码段

  …………

}

finish = clock();

//得到两次记录之间的时间差

costtime = (float)(finish - start) / CLOCKS_PER_SEC; 

时钟计时单元的长度为1毫秒,那么计时的精度也为1毫秒

<3>事件event

cudaEvent_t start,stop;

cudaEventCreate(&start);

cudaEventCreate(&stop);

cudaEventRecend(start,0);

{

  //统计的代码段

   …………

}

cudaEventRecord(stop,0);

float costtime;

cudaEventElapsedTime(&costtime,start,stop);

 
cudaError_t cudaEventCreate( cudaEvent_t* event )---创建事件对象;
cudaError_t cudaEventRecord( cudaEvent_t event,CUstream
stream )--- 记录事件;
cudaError_t
cudaEventElapsedTime( float* time,cudaEvent_t start,cudaEvent_t
end )---计算两次事件之间相差的时间;
cudaError_t
cudaEventDestroy( cudaEvent_t event )---销毁事件对象。
计算两次事件之间相差的时间(以毫秒为单位,精度为0.5微秒)。如果尚未记录其中任何一个事件,此函数将返回cudaErrorInvalidValue。如果记录其中任何一个事件使用了非零流,则结果不确定。

## CUDA代码常用编写技巧

1. 声明 __shared__ 变量或数组:

__shared__ float sh_farr[ 256];

__shared__ int a;

2.结构体指针成员的分配设备内存:

typedef struct Teacher_t

...{

    int a;

    unsigned int    *g_mem1;

    float            *g_mem2;

}Teacher;

void initMem( Teacher& t, const unsigned int mat_size) 

...{

    unsigned int mat_size_ui = sizeof(int) * mat_size;

    unsigned int mat_size_f = sizeof(float) * mat_size;

    CUDA_SAFE_CALL( cudaMalloc((void**)&t.g_mem1, mat_size_ui) );

    CUDA_SAFE_CALL( cudaMalloc((void**)&t.g_mem1, mat_size_f) );

    ...

}

3.计时:

unsigned int timer = 0;

CUT_SAFE_CALL( cutCreateTimer( &timer));

CUT_SAFE_CALL( cutStartTimer( timer));

...{

      ...//kernel

}

CUT_SAFE_CALL( cutStopTimer( timer));

printf( "Total time: %f ms ", cutGetTimerValue( timer) );

    CUT_SAFE_CALL( cutDeleteTimer( timer));

4. 获取输入命令行中包含的文件名:

/**/////////////////////////////////////////////////////////////////////////////////

//! Check if a particular filename has to be used for the file where the result

//! is stored

//! @param argc number of command line arguments (from main(argc, argv)

//! @param argv pointers to command line arguments (from main(argc, argv)

//! @param filename filename of result file, updated if user specified

//!                   filename

/**/////////////////////////////////////////////////////////////////////////////////

void

getResultFilename( int argc, char** argv, char*& filename) 

...{

char* temp = NULL;

    cutGetCmdLineArgumentstr( argc, (const char**) argv, "filename-result", &temp);

    if( NULL != temp) 

    ...{

        filename = (char*) malloc( sizeof(char) * strlen( temp));

        strcpy( filename, temp);

        cutFree( temp);

    }

    printf( "Result filename: '%s' ", filename);

}

类似的:

/**/////////////////////////////////////////////////////////////////////////////////

//! Check if a specific precision of the eigenvalue has to be obtained

//! @param argc number of command line arguments (from main(argc, argv)

//! @param argv pointers to command line arguments (from main(argc, argv)

//! @param iters_timing numbers of iterations for timing, updated if a 

//!                      specific number is specified on the command line

/**/////////////////////////////////////////////////////////////////////////////////

void

getPrecision( int argc, char** argv, float& precision)

...{

    float temp = -1.0f;

    cutGetCmdLineArgumentf( argc, (const char**) argv, "precision", &temp);

    if( temp > 0.0f) 

    ...{

        precision = temp;

    }

    printf( "Precision: %f ", precision);

}

5.Host调用完kernel函数需要进行线程同步,而在kernel或global函数只需要在必要的地方__syncthreads();即可:

CUDA_SAFE_CALL( cudaThreadSynchronize());

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/dvchn/archive/2008/02/25/2119590.aspx

【CUDA开发】CUDA开发琐碎知识的更多相关文章

  1. CUDA并行程序设计 开发环境搭建与远程调试

    课题需要用到GPU加速.目前使用的台式电脑只有核心显卡,而实验室有一台服务器装有NVIDIA GTX980独显.因此,想搭建一个CUDA的开发环境,来实现在台式机上面开发cuda程序,程序在服务器而不 ...

  2. CUDA开发 - CUDA 版本

    "CUDA runtime is insufficient with CUDA driver"CUDA 9.2: 396.xx CUDA 9.1: 387.xx CUDA 9.0: ...

  3. 前端开发:css基础知识之盒模型以及浮动布局。

    前端开发:css基础知识之盒模型以及浮动布局 前言 楼主的蛮多朋友最近都在学习html5,他们都会问到同一个问题 浮动是什么东西?  为什么这个浮动没有效果?  这个问题楼主已经回答了n遍.今天则是把 ...

  4. iOS开发学习概述及知识整理

    设计师设计出来了一个不错的引导界面,然而当我看到设计稿的时候,我们的app也没几天就要上线了.这个界面模仿了Evernote iOS app的风格. 我以迅雷不及掩耳盗铃之势开始在Xcode上编程,用 ...

  5. SQL点滴17—使用数据库引擎存储过程,系统视图查询,DBA,BI开发人员必备基础知识

    原文:SQL点滴17-使用数据库引擎存储过程,系统视图查询,DBA,BI开发人员必备基础知识 在开发过程中会遇到需要弄清楚这个数据库什么时候建的,这个数据库中有多少表,这个存储过程长的什么样子等等信息 ...

  6. 第二章 Odoo 12开发之开发环境准备

    在更深入了解 Odoo 开发之前,我们应配置好开发环境并学习相关的基础管理任务.本文中,我们将学习创建 Odoo 应用所需用到的工具和环境配置.这里采用 Ubuntu 系统来作为开发服务器实例的主机, ...

  7. XE7 & IOS开发之开发账号(3):证书、AppID、设备、授权profile的申请使用,附Debug真机调试、Ad hoc下iPA文件生成演示(XCode5或以上版本推荐,有图有真相)

    网上能找到的关于Delphi XE系列的移动开发的相关文章甚少,本文尽量以详细的图文内容.傻瓜式的表达来告诉你想要的答案. 原创作品,请尊重作者劳动成果,转载请注明出处!!! 注意,以下讨论都是以&q ...

  8. XE7 & IOS开发之开发账号(2):发布证书、发布授权profile的申请使用,附Ad hoc真机调试、生成ipa文件演示(XCode所有版本通用,有图有真相)

    网上能找到的关于Delphi XE系列的移动开发的相关文章甚少,本文尽量以详细的图文内容.傻瓜式的表达来告诉你想要的答案. 原创作品,请尊重作者劳动成果,转载请注明出处!!! 注意,以下讨论都是以&q ...

  9. XE7 & IOS开发之开发账号(1):开发证书、AppID、设备、开发授权profile的申请使用,附Debug真机调试演示(XCode所有版本通用,有图有真相)

    网上能找到的关于Delphi XE系列的移动开发的相关文章甚少,本文尽量以详细的图文内容.傻瓜式的表达来告诉你想要的答案. 原创作品,请尊重作者劳动成果,转载请注明出处!!! 注意,以下讨论都是以&q ...

  10. Spark集群 + Akka + Kafka + Scala 开发(3) : 开发一个Akka + Spark的应用

    前言 在Spark集群 + Akka + Kafka + Scala 开发(1) : 配置开发环境中,我们已经部署好了一个Spark的开发环境. 在Spark集群 + Akka + Kafka + S ...

随机推荐

  1. 特别的表格(overflow:hidden的一个小应用)

    做多个li,对各个边的边框有不同的要求,三层盒子,第一层盒子放li,设置右边和下边的虚线边框,浮动,第二层盒子ul设置宽度使li排列,第三层盒子最大的盒子,使用overflow:hidden,宽度高度 ...

  2. emacs源码安装

    1.源码下载地址=>下载 选择下载的版本,我下的是emacs-26.1.tar.xz 版本 2.解压 xz -d emacs-26.1.tar.xz # 解压成tar文件 tar -xvf em ...

  3. AtCoder Grand Contest 008题解

    传送门 \(A\) 分类讨论就行了 然而我竟然有一种讨论不动的感觉 int x,y; inline int min(R int x,R int y){return x<y?x:y;} inlin ...

  4. 64位内核开发第六讲,Windbg调试ring3跟Ring0.一起调试

    目录 驱动第六讲_Windbg连续调试Ring3.与Ring0 一丶Windbg连调试 驱动第六讲_Windbg连续调试Ring3.与Ring0 一丶Windbg连调试 有时候我们调试一个程序.可以使 ...

  5. luogu_P3313 [SDOI2014]旅行

    传送门 Solution 第二次学习可持久化线段树 打了一道裸题来练习一下-- 对于每个宗教都可以开一个主席树 基础操作 树剖lca Code  #include<bits/stdc++.h&g ...

  6. setTimeout 的理解

    setTimeout,延迟一段时间执行代码. setTimeout(func,0),这代码的作用并不是简单地和直接调用func一个效果: 1:动态往DOM树中插入元素,然后立刻操作这个元素(选择文本框 ...

  7. ubuntu之路——day11.1 如何进行误差分析

    举个例子 还是分类猫图片的例子 假设在dev上测试的时候,有100张图片被误分类了.现在要做的就是手动检查所有被误分类的图片,然后看一下这些图片都是因为什么原因被误分类了. 比如有些可能因为被误分类为 ...

  8. 第十七周助教工作总结——NWNU李泓毅

    助教博客链接:https://www.cnblogs.com/NWNU-LHY/ 本次作业的要求:软件测试与ALPHA冲刺:https://www.cnblogs.com/nwnu-daizh/p/1 ...

  9. vue element-UI 多个 select 回显成功,但是选中无反应

    参考文章 vue开发(四)element的select下拉框设定初值后,不能重新选择的问题 参考文章 element模态框dialog中的select组件中选中无反应 原因 下拉框数据是循环别的接口得 ...

  10. html5表单重写

    html5表单重写 一.总结 一句话总结: 表单重写用于在提交按钮上指定表单提交的各种信息,比如action <input type="submit" value=" ...