0_Simple__simplePitchLinearTexture
对比设备线性二维数组和 CUDA 二维数组在纹理引用中的效率
▶ 源代码。分别绑定相同大小的设备线性二维数组和 CUDA 二维数组为纹理引用,做简单的平移操作,重复若干次计算带宽和访问速度。
#include <stdio.h>
#ifdef _WIN32
# define WINDOWS_LEAN_AND_MEAN
# define NOMINMAX
# include <windows.h>
#endif
#include <cuda_runtime.h>
#include "device_launch_parameters.h"
#include <helper_functions.h>
#include <helper_cuda.h> #define NUM_REPS 100 // test 重复次数
#define TILE_DIM 16 // 线程块尺寸 texture<float, , cudaReadModeElementType> texRefPL;
texture<float, , cudaReadModeElementType> texRefArray; __global__ void shiftPitchLinear(float *odata, int pitch, int width, int height, int shiftX, int shiftY)
{
int xid = blockIdx.x * blockDim.x + threadIdx.x;
int yid = blockIdx.y * blockDim.y + threadIdx.y; odata[yid * pitch + xid] = tex2D(texRefPL, (xid + shiftX) / (float)width, (yid + shiftY) / (float)height);
} __global__ void shiftArray(float *odata, int pitch, int width, int height, int shiftX, int shiftY)
{
int xid = blockIdx.x * blockDim.x + threadIdx.x;
int yid = blockIdx.y * blockDim.y + threadIdx.y; odata[yid * pitch + xid] = tex2D(texRefArray, (xid + shiftX) / (float)width, (yid + shiftY) / (float)height);
} bool test()
{
bool result = true;
int i, j, ishift, jshift;
// 数组大小以及 x,y 方向上的偏移量
const int nx = ;
const int ny = ;
const int x_shift = ;
const int y_shift = ;
if ((nx % TILE_DIM) || (ny % TILE_DIM))
{
printf("nx and ny must be multiples of TILE_DIM\n");
return EXIT_FAILURE;
}
dim3 dimGrid(nx / TILE_DIM, ny / TILE_DIM), dimBlock(TILE_DIM, TILE_DIM); cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop); //int devID = findCudaDevice(argc, (const char **)argv);// 使用device 0,不再使用命令行参数进行判断 // 申请内存
float *h_idata = (float *)malloc(sizeof(float) * nx * ny);
float *h_odata = (float *)malloc(sizeof(float) * nx * ny);
float *h_ref = (float *)malloc(sizeof(float) * nx * ny);
for (int i = ; i < nx * ny; ++i)
h_idata[i] = (float)i;
float *d_idataPL;
size_t d_pitchBytes;
cudaMallocPitch((void **)&d_idataPL, &d_pitchBytes, nx * sizeof(float), ny);
cudaArray *d_idataArray;
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
cudaMallocArray(&d_idataArray, &channelDesc, nx, ny);
float *d_odata;
cudaMallocPitch((void **)&d_odata, &d_pitchBytes, nx * sizeof(float), ny); // 拷贝内存(两组)
size_t h_pitchBytes = nx * sizeof(float);
cudaMemcpy2D(d_idataPL, d_pitchBytes, h_idata, h_pitchBytes, nx * sizeof(float), ny, cudaMemcpyHostToDevice);
cudaMemcpyToArray(d_idataArray, , , h_idata, nx * ny * sizeof(float), cudaMemcpyHostToDevice); // 绑定纹理(两组)
texRefPL.normalized = ;
texRefPL.filterMode = cudaFilterModePoint;
texRefPL.addressMode[] = cudaAddressModeWrap;
texRefPL.addressMode[] = cudaAddressModeWrap;
cudaBindTexture2D(, &texRefPL, d_idataPL, &channelDesc, nx, ny, d_pitchBytes); texRefArray.normalized = ;
texRefArray.filterMode = cudaFilterModePoint;
texRefArray.addressMode[] = cudaAddressModeWrap;
texRefArray.addressMode[] = cudaAddressModeWrap;
cudaBindTextureToArray(texRefArray, d_idataArray, channelDesc); // 理论计算结果
for (i = ; i < ny; i++)
{
for (j = ; j < nx; ++j)
h_ref[i * nx + j] = h_idata[(i + y_shift) % ny * nx + (j + x_shift) % nx];
} // 使用线性数组的纹理计算
cudaMemset2D(d_odata, d_pitchBytes, , nx * sizeof(float), ny);
cudaEventRecord(start, );
for (int i = ; i < NUM_REPS; ++i)
shiftPitchLinear << <dimGrid, dimBlock >> > (d_odata, (int)(d_pitchBytes / sizeof(float)), nx, ny, x_shift, y_shift);
cudaEventRecord(stop, );
cudaEventSynchronize(stop);
float timePL;
cudaEventElapsedTime(&timePL, start, stop); // 检查结果
cudaMemcpy2D(h_odata, h_pitchBytes, d_odata, d_pitchBytes, nx * sizeof(float), ny, cudaMemcpyDeviceToHost);
if (!compareData(h_ref, h_odata, nx*ny, 0.0f, 0.15f))
{
printf("\n\t ShiftPitchLinear failed\n");
result = false;
} // 使用 CUDA数组的纹理计算
cudaMemset2D(d_odata, d_pitchBytes, , nx * sizeof(float), ny);
cudaEventRecord(start, );
for (int i = ; i < NUM_REPS; ++i)
shiftArray << <dimGrid, dimBlock >> > (d_odata, (int)(d_pitchBytes / sizeof(float)), nx, ny, x_shift, y_shift);
cudaEventRecord(stop, );
cudaEventSynchronize(stop);
float timeArray;
cudaEventElapsedTime(&timeArray, start, stop); // 检查结果
cudaMemcpy2D(h_odata, h_pitchBytes, d_odata, d_pitchBytes, nx * sizeof(float), ny, cudaMemcpyDeviceToHost);
if (!compareData(h_ref, h_odata, nx*ny, 0.0f, 0.15f))
{
printf("\n\tShiftArray failed\n");
result = false;
} // 计算带宽和读取速度
float bandwidthPL = .f * nx * ny * sizeof(float) / (timePL / .f / NUM_REPS * .e+9f);
float bandwidthArray = .f * nx * ny * sizeof(float) / (timeArray / .f / NUM_REPS * .e+9f);
printf("\n\tBandwidth for pitch linear: %.2f GB/s; for array: %.2f GB/s\n", bandwidthPL, bandwidthArray);
float fetchRatePL = nx * ny / .e+6f / (timePL / 1000.0f / NUM_REPS);
float fetchRateArray = nx * ny / .e+6f / (timeArray / 1000.0f / NUM_REPS);
printf("\n\tTexture fetch rate for pitch linear: %.2f Mpix/s; for array: %.2f Mpix/s\n", fetchRatePL, fetchRateArray); // 回收工作
free(h_idata);
free(h_odata);
free(h_ref);
cudaUnbindTexture(texRefPL);
cudaUnbindTexture(texRefArray);
cudaFree(d_idataPL);
cudaFreeArray(d_idataArray);
cudaFree(d_odata);
cudaEventDestroy(start);
cudaEventDestroy(stop); return result;
} int main(int argc, char **argv)
{
printf("\n\tStart\n");
printf("\n\tFinished, %s\n", test() ? "Passed" : "Failed"); getchar();
return ;
}
▶ 输出结果
Start
Bandwidth for pitch linear: 12.58 GB/s; for array: 14.64 GB/s
Texture fetch rate for pitch linear: 1573.09 Mpix/s; for array: 1829.39 Mpix/s
Finished, Passed
▶ 涨姿势
● 用到的函数都在以前的,有关线性二维数组和纹理内存使用方法的博客汇总讨论过了。
● 由运行结果可知,使用二维纹理引用时,CUDA 二维数组的效率比线性二维数组更高。
0_Simple__simplePitchLinearTexture的更多相关文章
随机推荐
- LOJ2540. 「PKUWC2018」随机算法【概率期望DP+状压DP】
LINK 思路 首先在加入几个点之后所有的点都只有三种状态 一个是在独立集中,一个是和独立集联通,还有一个是没有被访问过 然后前两个状态是可以压缩起来的 因为我们只需要记录下当前独立集大小和是否被访问 ...
- 【BZOJ2683】简单题
cdq分治妙啊 (被改过题面的)原题: dydxh所出的题目是这样的:有一个N*N矩阵,给出一系列的修改和询问,修改是这样的:将(x,y)中的数字加上k,而询问是这样的:求(x1,y1)到(x2,y2 ...
- cuda+ffmpeg+opengl解码rtsp h264码流多路
Cuda 解码 全尺寸 解码 .全尺寸窗口绘制测试( 分别 测试 视频 文件和 IP 相机 实时视频 ) 1080 p 视屏 文件 全尺寸 解码 全尺寸 显示 72 0p IP 相机 全尺寸 解码 全 ...
- 纯CSS绘制三角形(各种角度)类似于使用字符画法,根据位移不同,也可以使用两个元素画出三角边框
我们的网页因为 CSS 而呈现千变万化的风格.这一看似简单的样式语言在使用中非常灵活,只要你发挥创意就能实现很多比人想象不到的效果.特别是随着 CSS3 的广泛使用,更多新奇的 CSS 作品涌现出来. ...
- 杨恒说李的算法好-我问你听谁说的-龙哥说的(java中常见的List就2个)(list放入的是原子元素)
1.List中常用的 方法集合: 函数原型 ******************************************* ********************************** ...
- nexus && minio s3 存储私有镜像
对于新版本的nexus 已经支持s3 存储了(3.12),但是企业内部可能还是需要使用私有部署的 还好我们有minio,具体的介绍就不说了 minio 项目运行 参考项目: https://githu ...
- Cocos2d-X数据、动作、消息的基本操作
加入类的create方法: CREATE_FUNC(ClassName) 使用这个宏能够为类加入一个create方法. 创建类的对象时一律用Class::create()的形式. 在CREATE_FU ...
- juc并发工具类之CountDownLatch闭锁
import java.util.concurrent.CountDownLatch; /** * 闭锁: 在进行某些运算时, 只有其他所有线程的运算全部完成,当前运算才继续执行(程序流中加了一道栅栏 ...
- NOSQL之REDIS
Redis是NoSQL中比较常典型的一个非关系型数据库,在日常工作中也是最为常见的.Redis是一个由C语言编写的开源的.遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value数据 ...
- Linq to sql 增删改查(转帖)
http://blog.csdn.net/pan_junbiao/article/details/7015633 (LINQ To SQL 语法及实例大全) 代码 Code highlightin ...