该函数底层是cpu在拷贝还是gpu在拷贝,考入考出耗时这么大,gpu加速计算时是怎么加速的,原理是什么,程序应该怎么设计?
2条回答 默认 最新
- 关注
码龄 粉丝数 原力等级 --
- 被采纳
- 被点赞
- 采纳率
hello_hi_hi 2017-10-18 09:46最佳回答 专家已采纳cudaMemcopy是CPU和GPU两者共同作用的结果。
GPU编程就是八股文,共分三个步骤:
1、在启动GPU计算前使用cudaMemcopy将计算机内存的数据拷贝入GPU内存中,
2、启动GPU计算
3、GPU计算结束后使用cudaMemcopy将GPU内存中的计算结果返回CPU内存中。
由于数据交换通过PCI-E接口进行,只要数据俩不是太大且接口数据带宽足够,耗时不会很大!
GPU加速主要适用于高并行度、高计算量、低内存占用的项目。
1、高并行度——充分利用GPU中众多处理器的特点,根据不同的GPU可用成千上万个线程并行处理;
2、高计算量——可以抵消cudaMemcopy带来的影响
3、低内存占用——尽量使用局部内存,减少对显存的使用,从而减少由于访问显存而带来的时延。
下面是一个完整的例子:
CudaSample.h
#ifndef HEADER_THREADTEST_H
#define HEADER_THREADTEST_H
#ifdef __cplusplus
extern "C" {
#endif//CUDA device property data structure
struct DevicdProp
{
int deviceNo;
char name[256];
size_t totalGlobalMem;
size_t sharedMemPerBlock;
int regsPerBlock;
int warpSize;
size_t memPitch;
int maxThreadsPerBlock;
int maxThreadsDim[3];
int maxGridSize[3];
size_t totalConstMem;
int major;
int minor;
int clockRate;
size_t textureAlignment;
int deviceOverlap;
int multiProcessorCount;
};//thread number is equal to 2 multiprocessor's thread number
#define ThreadNumPerBlock 64#define BlockNum 4
#define TotalThread BlockNum * ThreadNumPerBlock
//Self defined structure
struct MYSTRUCT
{
unsigned int A[TotalThread], B[TotalThread], C[TotalThread];
};//Init CUDA
bool InitCUDA(DevicdProp *lpDevicdProp);//Cuda Sample
void CudaSample(MYSTRUCT* lpHostStruct);#ifdef __cplusplus
}
#endif
#endifCudaCuda.cu
#include
#include#include
#include "CudaSample.h"
/************************************************************************/
/* Init CUDA /
/***********************************************************************/
cudaDeviceProp deviceProp;#if DEVICE_EMULATION
bool InitCUDA(DevicdProp *lpDevicdProp){return true;}
#else
bool InitCUDA(DevicdProp *lpDevicdProp)
{
int count = 0;
int i = 0;//Set no CUDA device is selected lpDevicdProp->deviceNo = -1; cudaGetDeviceCount(&count); if(count == 0) { fprintf(stderr, "There is no device.\n"); return false; } else printf("\n\nThere are maybe %d devices supporting CUDA\n", count); for(i = 0; i < count; i++) { if(cudaGetDeviceProperties(&deviceProp, i) != cudaSuccess) { printf("\nDevice %d: Property cannot be get.\n", i); continue; } // This function call returns 9999 for both major & minor fields, if no CUDA capable devices are present if(deviceProp.major == 9999 && deviceProp.minor == 9999) { printf("\nDevice %d: Do not supporting CUDA.\n", i); continue; } if(lpDevicdProp->deviceNo == -1) { lpDevicdProp->deviceNo = i; memcpy(lpDevicdProp->name, deviceProp.name, 256); lpDevicdProp->totalGlobalMem = deviceProp.totalGlobalMem; lpDevicdProp->sharedMemPerBlock = deviceProp.sharedMemPerBlock; lpDevicdProp->regsPerBlock = deviceProp.regsPerBlock; lpDevicdProp->warpSize = deviceProp.warpSize; lpDevicdProp->memPitch = deviceProp.memPitch; lpDevicdProp->maxThreadsPerBlock = deviceProp.maxThreadsPerBlock; lpDevicdProp->maxThreadsDim[0] = deviceProp.maxThreadsDim[0]; lpDevicdProp->maxThreadsDim[1] = deviceProp.maxThreadsDim[1]; lpDevicdProp->maxThreadsDim[2] = deviceProp.maxThreadsDim[2]; lpDevicdProp->maxGridSize[0] = deviceProp.maxGridSize[0]; lpDevicdProp->maxGridSize[1] = deviceProp.maxGridSize[1]; lpDevicdProp->maxGridSize[2] = deviceProp.maxGridSize[2]; lpDevicdProp->totalConstMem = deviceProp.totalConstMem; lpDevicdProp->major = deviceProp.major; lpDevicdProp->minor = deviceProp.minor; lpDevicdProp->clockRate = deviceProp.clockRate; lpDevicdProp->textureAlignment = deviceProp.textureAlignment; lpDevicdProp->deviceOverlap = deviceProp.deviceOverlap; lpDevicdProp->multiProcessorCount = deviceProp.multiProcessorCount; } printf("\nDevice %d: \"%s\"\n", i, deviceProp.name); printf(" CUDA Capability Major revision number: %d\n", deviceProp.major); printf(" CUDA Capability Minor revision number: %d\n", deviceProp.minor); printf(" Total amount of global memory: %u bytes\n", (unsigned int)(deviceProp.totalGlobalMem));
#if CUDART_VERSION >= 2000
printf(" Number of multiprocessors: %d\n", deviceProp.multiProcessorCount);
printf(" Number of cores: %d\n", 8 * deviceProp.multiProcessorCount);
#endif
printf(" Total amount of constant memory: %u bytes\n", (unsigned int)(deviceProp.totalConstMem));
printf(" Total amount of shared memory per block: %u bytes\n", (unsigned int)(deviceProp.sharedMemPerBlock));
printf(" Total number of registers available per block: %d\n", deviceProp.regsPerBlock);
printf(" Warp size: %d\n", deviceProp.warpSize);
printf(" Maximum number of threads per block: %d\n", deviceProp.maxThreadsPerBlock);
printf(" Maximum sizes of each dimension of a block: %d x %d x %d\n",
deviceProp.maxThreadsDim[0],
deviceProp.maxThreadsDim[1],
deviceProp.maxThreadsDim[2]);
printf(" Maximum sizes of each dimension of a grid: %d x %d x %d\n",
deviceProp.maxGridSize[0],
deviceProp.maxGridSize[1],
deviceProp.maxGridSize[2]);
printf(" Maximum memory pitch: %u bytes\n", (unsigned int)(deviceProp.memPitch));
printf(" Texture alignment: %u bytes\n", (unsigned int)(deviceProp.textureAlignment));
printf(" Clock rate: %.2f GHz\n", deviceProp.clockRate * 1e-6f);
#if CUDART_VERSION >= 2000
printf(" Concurrent copy and execution: %s\n", deviceProp.deviceOverlap ? "Yes" : "No");
#endif
#if CUDART_VERSION >= 2020
printf(" Run time limit on kernels: %s\n", deviceProp.kernelExecTimeoutEnabled ? "Yes" : "No");
printf(" Integrated: %s\n", deviceProp.integrated ? "Yes" : "No");
printf(" Support host page-locked memory mapping: %s\n", deviceProp.canMapHostMemory ? "Yes" : "No");
printf(" Compute mode: %s\n", deviceProp.computeMode == cudaComputeModeDefault ?
"Default (multiple host threads can use this device simultaneously)" :
deviceProp.computeMode == cudaComputeModeExclusive ?
"Exclusive (only one host thread at a time can use this device)" :
deviceProp.computeMode == cudaComputeModeProhibited ?
"Prohibited (no host thread can use this device)" :
"Unknown");
#endif
}i = lpDevicdProp->deviceNo; if(i == -1) { fprintf(stderr, "There is no device supporting CUDA.\n"); return false; } cudaSetDevice(i); printf("CUDA Device No. used = %d.\n", i); printf("CUDA initialized.\n"); return true;
}
/************************************************************************/
/* Example /
/***********************************************************************/
global static void CudaCalc(MYSTRUCT* lpMyStruct)
{
int idx = threadIdx.x + blockIdx.x * blockDim.x;if(gridDim.x!=BlockNum) return; if(blockDim.x!=ThreadNumPerBlock) return; if(idx<TotalThread) lpMyStruct->A[idx] = lpMyStruct->B[idx] + lpMyStruct->C[idx];
}
void CudaSample(MYSTRUCT* lpHostStruct)
{MYSTRUCT *lpDeviceStruct = 0; cudaMalloc((void**) &lpDeviceStruct, sizeof(MYSTRUCT)); cudaMemcpy(lpDeviceStruct, lpHostStruct, sizeof(MYSTRUCT), cudaMemcpyHostToDevice); CudaCalc<<<BlockNum, ThreadNumPerBlock, 0>>>(lpDeviceStruct);
// CUT_CHECK_ERROR("Kernel execution failed\n");
cudaThreadSynchronize(); cudaMemcpy(lpHostStruct, lpDeviceStruct, sizeof(MYSTRUCT), cudaMemcpyDeviceToHost); cudaFree(lpDeviceStruct);
}
#endif
CudaSample.cpp
#include
#include#include "CudaSample.h"
int main(int argc, char* argv[])
{
DevicdProp DevicdProps;
MYSTRUCT MyStruct;
unsigned int I, J, N;if(!InitCUDA(&DevicdProps)) return 1; for(I=0; I<TotalThread; I++) { MyStruct.B[I] = I; MyStruct.C[I] = I; } CudaSample(&MyStruct); for(I=0; I<TotalThread; I++) J = MyStruct.A[I]; return 0;
}
这个例子基本涵盖了用CUDA进行GPU编程的必要步骤(尚缺根据不同GPU选择不同的线程数以及在CPU中启用多线程进行多GPU并行计算)
其计算为
for(I=0; I<TotalThread; I++)
{
MyStruct.B[I] = I;
MyStruct.C[I] = I;
MyStruct.A[I] = MyStruct.B[I] + MyStruct.C[I];
}
其中MyStruct.A[I] = MyStruct.B[I] + MyStruct.C[I]在GPU中计算,每个线程算一个,总线程数为256个。采纳该答案 已采纳该答案 专家已采纳评论解决 无用打赏举报微信扫一扫
分享评论登录 后可回复...
报告相同问题?
相关推荐 更多相似问题
- 2017-10-18 06:30回答 2 已采纳 cudaMemcopy是CPU和GPU两者共同作用的结果。 GPU编程就是八股文,共分三个步骤: 1、在启动GPU计算前使用cudaMemcopy将计算机内存的数据拷贝入GPU内存中, 2、启动
- 2019-07-17 11:27回答 6 已采纳 经过自己测试(可以在visual studio上编写CUDA程序),确实是支持的。
- 2017-06-10 16:27回答 2 已采纳 后来重装cuda8.0时发现,应该先安装VS2013然后才安装cuda8.0,因为安装cuda8.0时,它会配置VS2013,如果安装顺序相反,则新建项目的时候,没有nvidia模块。
- 2019-09-06 10:22CUDA编程指南 中文版5.0 CUDA编程指南 中文版
- 2017-12-29 16:05基于CUDA官方文件翻译,包括cuda编程模型、编程接口、硬件实现、性能指南、C语言扩展、数学函数、纹理获取、计算能力、驱动API等获取等介绍。
- 2018-11-06 10:43CUDA C 编程指南,美国华裔教授大牛程润伟最新力作,学习CUDA必备经典图书
- 2022-04-24 19:06回答 2 已采纳 CUDA-Threadhttps://wenku.baidu.com/view/c3da123e2179168884868762caaedd3383c4b57a.html
- 2016-03-02 21:47回答 1 已采纳 It appears, at least in this case, that the go import of C is expecting the function to be provid
- 2022-04-24 20:17回答 2 已采纳 调用核函数的时候,可以有多个block,,每个block所能容纳的最大线程数也是有限的。其实在硬件上,每个block里面的所有thread会共用一个处理器核心,而且它们共享的shared memory
- 2014-05-17 15:58GPU高性能编程CUDA实战.pdf GPU高性能运算之CUDA.pdf CUDA平台下多核GPU高性能并行编程研究.pdf
- 2021-05-19 11:25随便写点笔记的博客 1.向量相加的cuda实现 (按对应位置相加) #include <iostream> #include <cuda_runtime.h> #define length 10000 //__global__ int foo(int a){}表示一个内核函数, //是一组由GPU执行的并行计算...
- 2013-02-26 16:421. 文档是从http://cudazone.nvidia.cn/forum/forum.php?mod=viewthread&tid=6266&extra=page=1下载来的,是“yyfn风辰”翻译的文档,原文档是装好cuda sdk后名字为“CUDA_C_Programming_Guide.pdf”的文档 ...
- 2018-07-15 08:54回答 5 已采纳 代码是在设备上运行的么,没有使用主机变量吧,没有爆内存吧,还有驱动程序对不对。你可以先测试自带的例子程序,排除环境问题。
- 2018-09-13 07:53回答 1 已采纳 https://blog.csdn.net/u012348774/article/details/49663299
- 2018-11-10 14:08回答 3 已采纳 运行cuda 8.0的samples里面的devicequery,看下你的卡,是否安装正确了。并且计算能力是不是>3.0 410这个显卡,虽然号称“专业卡”,但是实际上性能连市面上100块钱价
- 2021-11-12 21:49DU_YULIN的博客 VS2017 CUDA编程学习1:CUDA编程两变量加法运算 VS2017 CUDA编程学习2:在GPU上执行线程 VS2017 CUDA编程学习3:CUDA获取设备上属性信息 VS2017 CUDA编程学习4:CUDA并行处理初探 - 向量加法实现 VS2017 CUDA编程...
- 2021-11-20 19:56A-Egoist的博客 CUDA编程入门 更好的阅读体验 CUDA 概述 CUDA 是 NVIDIA 推出的用于其发布的 GPU 的并行计算架构,使用 CUDA 可以利用 GPU 的并行计算引擎更加高效的完成复杂的计算难题。 在目前主流的使用冯·诺依曼体系结构的...
- 2018-09-28 18:42Ahuier21的博客 CUDA编程模型简介CUDA编程模型1、编程结构2 内存层次结构成3 线程管理 CUDA编程模型 本篇博客主要对CUDA的编程模型、内存层次结构、线程管理进行简单的介绍。 1、编程结构 CUDA是一种通用的并行计算平台和编程...
- 2016-12-21 02:00回答 1 已采纳 支持的,只不过coalesced access效率更高
- 2019-06-11 12:55xiaoma_bk的博客 CUDA编程真的是入门容易精通难,具有计算机体系结构和C语言编程知识储备的同学上手CUDA编程应该难度不会很大。本文章将通过以下五个方面帮助大家比较全面地了解CUDA编程最重要的知识点,做到快速入门: GPU 架构...
- 没有解决我的问题, 去提问