0_Simple__cppOverload
▶ 使用 cuda 内置结构 cudaFuncAttributes 来观察核函数的共享内存、寄存器数量
▶ 源代码
// cppOverload_kernel.cu
__global__ void simple_kernel(const int *pIn, int *pOut, int a)
{
__shared__ int sData[THREAD_N];
int tid = threadIdx.x + blockDim.x * blockIdx.x; sData[threadIdx.x] = pIn[tid];
__syncthreads();
pOut[tid] = sData[threadIdx.x] * a + tid;
} __global__ void simple_kernel(const int2 *pIn, int *pOut, int a)
{
__shared__ int2 sData[THREAD_N];
int tid = threadIdx.x + blockDim.x * blockIdx.x; sData[threadIdx.x] = pIn[tid];
__syncthreads();
pOut[tid] = (sData[threadIdx.x].x + sData[threadIdx.x].y) * a + tid;
} __global__ void simple_kernel(const int *pIn1, const int *pIn2, int *pOut, int a)
{
__shared__ int sData1[THREAD_N], sData2[THREAD_N];
int tid = threadIdx.x + blockDim.x * blockIdx.x; sData1[threadIdx.x] = pIn1[tid];
sData2[threadIdx.x] = pIn2[tid];
__syncthreads();
pOut[tid] = (sData1[threadIdx.x] + sData2[threadIdx.x])*a + tid;
}
// cppOverload.cu
#include <stdio.h>
#include <helper_cuda.h>
#include <helper_math.h>
#include <helper_string.h> #define THREAD_N 256
#include "cppOverload_kernel.cu" // 源代码文件中使用了 THREAD_N,必须先定义 #define N 1024
#define DIV_UP(a, b) (((a) + (b) - 1) / (b))
#define OUTPUT_ATTR(attr) \
printf("Shared Size: %d\n", (int)attr.sharedSizeBytes); \
printf("Constant Size: %d\n", (int)attr.constSizeBytes); \
printf("Local Size: %d\n", (int)attr.localSizeBytes); \
printf("Max Threads Per Block: %d\n", attr.maxThreadsPerBlock); \
printf("Number of Registers: %d\n", attr.numRegs); \
printf("PTX Version: %d\n", attr.ptxVersion); \
printf("Binary Version: %d\n", attr.binaryVersion); bool check_func1(int *hInput, int *hOutput, int a)
{
for (int i = ; i < N; ++i)
{
int cpuRes = hInput[i] * a + i;
if (hOutput[i] != cpuRes)
return false;
}
return true;
} bool check_func2(int2 *hInput, int *hOutput, int a)
{
for (int i = ; i < N; i++)
{
int cpuRes = (hInput[i].x + hInput[i].y)*a + i;
if (hOutput[i] != cpuRes)
return false;
}
return true;
} bool check_func3(int *hInput1, int *hInput2, int *hOutput, int a)
{
for (int i = ; i < N; i++)
{
if (hOutput[i] != (hInput1[i] + hInput2[i])*a + i)
return false;
}
return true;
} int main(int argc, const char *argv[])
{
int deviceID = cudaSetDevice(); int *hInput = NULL, *hOutput = NULL, *dInput = NULL, *dOutput = NULL;
cudaMalloc(&dInput, sizeof(int)*N * );
cudaMalloc(&dOutput, sizeof(int)*N);
cudaMallocHost(&hInput, sizeof(int)*N * );
cudaMallocHost(&hOutput, sizeof(int)*N); for (int i = ; i < N * ; i++)
hInput[i] = i;
cudaMemcpy(dInput, hInput, sizeof(int)*N * , cudaMemcpyHostToDevice); const int a = ;
void(*func1)(const int *, int *, int) = simple_kernel;
void(*func2)(const int2 *, int *, int) = simple_kernel;
void(*func3)(const int *, const int *, int *, int) = simple_kernel;
struct cudaFuncAttributes attr; // function 1
memset(&attr, , sizeof(attr));
cudaFuncSetCacheConfig(*func1, cudaFuncCachePreferShared); // 运行前分析资源占用
cudaFuncGetAttributes(&attr, *func1);
OUTPUT_ATTR(attr);
(*func1) << <DIV_UP(N, THREAD_N), THREAD_N >> >(dInput, dOutput, a);
cudaDeviceSynchronize();
cudaMemcpy(hOutput, dOutput, sizeof(int)*N, cudaMemcpyDeviceToHost);
printf("simple_kernel(const int *pIn, int *pOut, int a) %s\n\n", check_func1(hInput, hOutput, a) ? "PASSED" : "FAILED"); // function 2
memset(&attr, , sizeof(attr));
cudaFuncSetCacheConfig(*func2, cudaFuncCachePreferShared);
cudaFuncGetAttributes(&attr, *func2);
OUTPUT_ATTR(attr);
(*func2) << <DIV_UP(N, THREAD_N), THREAD_N >> >((int2 *)dInput, dOutput, a); // 强行转换成 int2*,反正也是对其的
cudaMemcpy(hOutput, dOutput, sizeof(int)*N, cudaMemcpyDeviceToHost);
printf("simple_kernel(const int2 *pIn, int *pOut, int a) %s\n\n", check_func2(reinterpret_cast<int2 *>(hInput), hOutput, a) ? "PASSED" : "FAILED"); // function 3
memset(&attr, , sizeof(attr));
cudaFuncSetCacheConfig(*func3, cudaFuncCachePreferShared);
cudaFuncGetAttributes(&attr, *func3);
OUTPUT_ATTR(attr);
(*func3) << <DIV_UP(N, THREAD_N), THREAD_N >> >(dInput, dInput + N, dOutput, a);
cudaMemcpy(hOutput, dOutput, sizeof(int)*N, cudaMemcpyDeviceToHost);
printf("simple_kernel(const int *pIn1, const int *pIn2, int *pOut, int a) %s\n\n", check_func3(&hInput[], &hInput[N], hOutput, a) ? "PASSED" : "FAILED"); cudaFree(dInput);
cudaFree(dOutput);
cudaFreeHost(hOutput);
cudaFreeHost(hInput);
getchar();
return ;
}
● 输出结果:
Shared Size:
Constant Size:
Local Size:
Max Threads Per Block:
Number of Registers:
PTX Version:
Binary Version:
simple_kernel(const int *pIn, int *pOut, int a) PASSED Shared Size:
Constant Size:
Local Size:
Max Threads Per Block:
Number of Registers:
PTX Version:
Binary Version:
simple_kernel(const int2 *pIn, int *pOut, int a) PASSED Shared Size:
Constant Size:
Local Size:
Max Threads Per Block:
Number of Registers:
PTX Version:
Binary Version:
simple_kernel(const int *pIn1, const int *pIn2, int *pOut, int a) PASSED
▶ 涨姿势:
● cuda 使用扩展名为 .cuh 的头文件
● cuda内置结构 cudaFuncAttributes 的定义:
struct __device_builtin__ cudaFuncAttributes
{
size_t sharedSizeBytes; // 共享内存大小
size_t constSizeBytees; // 常量内存大小
size_t localSizeBytes; // 局部内存大小
int maxThreadsPerBlock; // 每线程块线最大程数量
int numRegs; // 寄存器数量
int ptxVersion; // PTX版本号
int binaryVersion; // 机器码版本号
int cacheModeCA; // 是否使用编译指令 -Xptxas --dlcm=ca
};
● 通过使用cuda的内置结构和函数来查看核函数使用的共享内存与寄存器数量
struct cudaFuncAttributes attr;
memset(&attr, , sizeof(attr));
cudaFuncSetCacheConfig(*function, cudaFuncCachePreferShared);
cudaFuncGetAttributes(&attr, *function);
■ 涉及的函数
extern __host__ cudaError_t CUDARTAPI cudaFuncSetCacheConfig(const void *func, enum cudaFuncCache cacheConfig); __device__ __attribute__((nv_weak)) cudaError_t cudaFuncGetAttributes(struct cudaFuncAttributes *p, const void *c)
{
return cudaErrorUnknown;
} #define OUTPUT_ATTR(attr) \
printf("Shared Size: %d\n", (int)attr.sharedSizeBytes); \
printf("Constant Size: %d\n", (int)attr.constSizeBytes); \
printf("Local Size: %d\n", (int)attr.localSizeBytes); \
printf("Max Threads Per Block: %d\n", attr.maxThreadsPerBlock); \
printf("Number of Registers: %d\n", attr.numRegs); \
printf("PTX Version: %d\n", attr.ptxVersion); \
printf("Binary Version: %d\n", attr.binaryVersion);
0_Simple__cppOverload的更多相关文章
随机推荐
- IOS7 点击空白处隐藏键盘的几种方法
IOS7 点击空白处隐藏键盘的几种方法 iOS开发中经常要用到输入框,默认情况下点击输入框就会弹出键盘,但是必须要实现输入框return的委托方法才能取消键盘的显示,对于用户体验来说很不友好,我们 ...
- 基于React Native的移动平台研发实践分享
转载:http://blog.csdn.net/haozhenming/article/details/72772787 本文目录: 一.React Native 已经成为了移动前端技术的趋势 二.基 ...
- Writing Science 笔记 6.19
1.练习由三个部分组成:写短文,反复修改:分析别人的文章是怎么写的:练习句子结构,如何用词. 2.写作的目的不在于发表而在于能够给人以灵感从而使文章得到更多的引用. 3.写得清楚,你必须清楚地思考,无 ...
- LInux ugo权限详解
Linux 中的用户和组是用来控制使用者或者进程可以或者不可以使用哪些资源和硬件,是Linux权限控制最基本的方式. 用户和组可以看一下上一章的部分,先来看一下权限. 一.权限概览 在Linux下,使 ...
- 计算机基础--Java中int char byte的关系
计算机基础--Java中int char byte的关系 重要:一个汉字占用2byte,Java中用char(0-65535 Unicode16)型字符来存字(直接打印输出的话是字而非数字),当然要用 ...
- UI自动化测试(二)浏览器操作及对元素的定位方法(xpath定位和css定位详解)
Selenium下的Webdriver工具支持FireFox(geckodriver). IE(InternetExplorerDriver).Chrome(ChromeDriver). Opera( ...
- HTML5基础知识及相关笔记
HTML5基础 1.1HTML文件的基本结构和W3C标准 1.1.1HTML简介 HTML是一种描述网页的语言,一种超文本标记的语言! 1.1.2HTML文件的基本结构 头部(head) 头部是网页的 ...
- ES6-模块化
ES6-模块化 在es6标准中,js原生支持modulele. ES6模块需要使用babel转码,这里简单解释一下什么是babel转码. babel就是将‘ES6模块化语法’转化为‘CommonJS模 ...
- Centos7虚拟机桥接模式
主机ping不通虚拟机centos7系统的ip大多有以下原因: 1.主机与centos7ip段对应 (关键是网关.dns服务器要一一对应,具体操作见后文) 2.对应后仍然不通的,可关闭主机与cenos ...
- 从 JavaScript 到 TypeScript 系列
随着应用的庞大,项目中 JavaScript 的代码也会越来越臃肿,这时候许多 JavaScript 的语言弊端就会愈发明显,而 TypeScript 的出现,就是着力于解决 JavaScript 语 ...