▶ 使用 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的更多相关文章

随机推荐

  1. 为什么你需要将代码迁移到ASP.NET Core 2.0?

    随着 .NET Core 2.0 的发布,.NET 开源跨平台迎来了新的时代.开发者们可以选择使用命令行.个人喜好的文本编辑器.Visual Studio 2017 15.3 和 Visual Stu ...

  2. css常用属性1

    1  背景相关 背景颜色 background-color     = 颜色名称/rgb值/十六进制值 背景图片 background-image = url('') 背景图片平铺方式 backgro ...

  3. linux cpu load学习笔记

    linux系统中的Load对当前CPU工作量的度量 Load Average 就是一段时间 (1 分钟.5分钟.15分钟) 内平均Load. [root@CNC-BJ-5-3N1 ~]# w 20:0 ...

  4. Windows下 如何添加开机启动项

    Windows XP,Windows 7: 开始 ----> 所有程序 ----> 启动, 右键打开"启动"这个文件夹, 把想开机自动启动的软件快捷方式拖进去即可. ( ...

  5. 我的Spring学习记录(四)

    虽然Spring管理这我们的Bean很方便,但是,我们需要使用xml配置大量的Bean信息,告诉Spring我们要干嘛,这还是挺烦的,毕竟当我们的Bean随之增多的话,xml的各种配置会让人很头疼. ...

  6. Even Parity uva11464 模拟

    Even Parity Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [Submit]   ...

  7. bzoj3224 普通平衡树(c++vector)

    Tyvj 1728 普通平衡树 2014年8月23日6,4365 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有 ...

  8. Docker入门之五数据管理

    在Docker使用过程中,需要对数据进行持久化或需要在多个容器之间进行数据共享,就会涉及容器的数据管理操作.主要有两种方式:1.数据卷 2.数据卷容器. 一.数据卷 数据卷是一个可供容器使用的特殊目录 ...

  9. java中需要注意的小细节

    很早以前就打算写博客,但是总是因为不知道写什么,或是觉得博客里其他人已经把我要写的整理很好了而迟迟没有动笔,现在决定把自己平时的记录的一些笔记拿出来,希望大神们可以批评指导,并且希望能够帮助一些刚刚入 ...

  10. 网时|云计算的集群技术对于传统IDC而言,又有哪些提高呢?

    当传统的IDC产品已经不足以满足现在科技的飞速发展时,云计算便应运而生.咱们暂且不论云计算在其他领域的贡献,仅IDC来讲,云计算的集群技术对于传统IDC而言,又有哪些提高呢? 1.服务类型 常用的传统 ...