DAY20:阅读Surface Memory

3.2.11.2. Surface Memory

For devices of compute capability 2.0 and higher, a CUDA array (described in Cubemap Surfaces), created with the cudaArraySurfaceLoadStore flag, can be read and written via a surface object or surface reference using the functions described in Surface Functions.

Table 14 lists the maximum surface width, height, and depth depending on the compute capability of the device.

(二维码扫描可以看到Table 14的图)

3.2.11.2.1. Surface Object API

A surface object is created using cudaCreateSurfaceObject() from a resource description of type struct cudaResourceDesc.

The following code sample applies some simple transformation kernel to a texture.

3.2.11.2.2. Surface Reference API

A surface reference is declared at file scope as a variable of type surface:

surface<void, Type> surfRef;

where Type specifies the type of the surface reference and is equal to cudaSurfaceType1D, cudaSurfaceType2D, cudaSurfaceType3D, cudaSurfaceTypeCubemap,cudaSurfaceType1DLayered, cudaSurfaceType2DLayered, or cudaSurfaceTypeCubemapLayered; Type is an optional argument which defaults to cudaSurfaceType1D. A surface reference can only be declared as a static global variable and cannot be passed as an argument to a function.

Before a kernel can use a surface reference to access a CUDA array, the surface reference must be bound to the CUDA array using cudaBindSurfaceToArray().

The following code samples bind a surface reference to a CUDA array cuArray:

· Using the low-level API:

· Using the high-level API:

A CUDA array must be read and written using surface functions of matching dimensionality and type and via a surface reference of matching dimensionality; otherwise, the results of reading and writing the CUDA array are undefined.

Unlike texture memory, surface memory uses byte addressing. This means that the x-coordinate used to access a texture element via texture functions needs to be multiplied by the byte size of the element to access the same element via a surface function. For example, the element at texture coordinate x of a one-dimensional floating-point CUDA array bound to a texture reference texRef and a surface reference surfRef is read using tex1d(texRef, x) via texRef, but surf1Dread(surfRef, 4*x) via surfRef. Similarly, the element at texture coordinate x and y of a two-dimensional floating-point CUDA array bound to a texture reference texRef and a surface reference surfRef is accessed using tex2d(texRef, x, y) via texRef, but surf2Dread(surfRef, 4*x, y) via surfRef (the byte offset of the y-coordinate is internally calculated from the underlying line pitch of the CUDA array).

The following code sample applies some simple transformation kernel to a texture.

本文备注/经验分享:

Surface Memory——

如同之前我们说过的, surface等于非常简化版本的texture,texture具有的特殊功能它都没有。例如texture的坐标变换,插值,高级边界处理之类的。还有图形学用的mipmap,lod啥的,但Surface同样可以绑定CUDA Array,同时可以写入。而普通指针读写只能应付普通的线性内存(显存)。以及,surface只有简单的边界处理,例如越界返回0(读取)或者越界写入忽略之类的。你应当将它当成一个极度简化版本的texture,或者当成只有存储读写功能,但没有采样器(sampler,也就是之前你看到的那些texture的高级特性)的简化版本texture。能写入这个非常重要——在以前没有写入功能的时候,更新CUDA Array非常麻烦,现在只需要在kernel上启动一个surface更新写入即可。这个是个很好的功能,否则以前需要从host端折腾,现在可以直接从device上启动kernel处理了。其他的都一样。

Surface Object API——

在这段演示的代码里面, 你会看到这个kernel很简化了,没有旋转功能了,只是简单的复制一张图片:读取原图,写入目标图。因为之前的那个旋转kernel的很多特性,例如从归一化的坐标进行插值这些,surface没有。所以这个kernel只是一个简化的什么都不干的kernel,但演示了surface可以直接写入的特性。

(1)更新CUDA Array的时候,texture是只读的,但这个可以对后备存储(CUDA Array)写入。可以用来更新一个CUDA Array给texture用,但需要注意的是,surface写入和texture读取不维持一致性,只有在下次kernel启动的时候才能生效,所以你往往能见到这种风格的代码——stream中:surface写入kernel---->texture读取kernel 这么一个顺序。

(2)你不需要复杂的texture功能,而只需要简单的越界处理(只有两种最简单的边界处理);

(3) 你可能需要surface访问CUDA Array,以便使用里面的特殊的,对用户不透明,但可能对程序性能有提升的存储方式。 大致这三种情况。

还有一点,就是纹理在不使用归一化坐标的时候,坐标的含义是点/元素/纹元。而surface的坐标是字节。里面有个元素大小的倍数差别。从texture改成surface的时候,需要注意这个坐标问题(假设surface能满足要求),其他应当都一样了。以及,刚才说过的不维持读写一致性这个很重要。写入surface必须在下次kernel启动才能生效。立刻读取将导致未定义的结果。

还有一点。surface必须绑定到Cuda array,

struct cudaResourceDesc resDesc; memset(&resDesc, 0, sizeof(resDesc)); resDesc.resType = cudaResourceTypeArray;

这三行代码中的resType,必须是cudaResourceTypeArray。手册没说,但是用线性内存这里会失败的。其实也很好理解。本身surface功能就少。如果再不使用CUDA Array,那就和普通的指针读写普通内存(显存)毫无区别了。(除了唯一剩下的防止越界)。那样的话又何必要用它了。所以这里要求必须的,这里不能使用cudaResourceTypeLinear,而必须是TypeArray。

Surface Reference API——

上面说的这些对object和reference都有效的。他们只是一个是老API,一个是新API而已。无本质区别的,类似texture reference和texture object的关系,纹理的特性是通用的,只是形式不同。surface同理。surface reference就比surface object早出了fermi这一代,从Fermi开始有的surface reference,但从Kepler就立刻更新了, 有了surface object。而texture reference是从一开头有CUDA就有的,不过它们两个都是从Kepler(3.0)开始,更新有了texture object和surface object,所以texture refernce独立存在的时间更长。老代码涉及texture reference的可能要远比surface reference的多。

The following code sample applies some simple transformation kernel to a texture.; 后面的代码没有什么特别的,但需要注意的是,从inputSurfRef读取后,没有经过任何处理,就写入了outputSurfRef。以前texture那段是有个旋转的。这个是原图,完全没转动。但:

(1)虽然没转动,但结果直接写入了一个输出的cuda array, 以后可以直接给需要该cuda array内容的texture用。而之前的例子只能写入普通内存。(因为texture无写入能力)

(2)这里没有使用outputSurfRef。如果要使用的话,必须在下次的kernel中才能使用它,本次如果使用了会导致未定义的结果。

(3)注意x坐标是一个乘以了4(元素大小)的整数。因为单位是字节。 而之前的texture坐标不需要*4, 同时是归一化的浮点值[0.0, 1.0)。

归一化的浮点坐标,这个属于texture独有的高级特性。不能使用的。(但可以自行用代码实现坐标变换,等效的实现这一点,只是不能自动免费实现了)

有不明白的地方,请在本文后留言

或者在我们的技术论坛bbs.gpuworld.cn上发帖

原文发布于微信公众号 - 吉浦迅科技(gpusolution)

原文发表时间:2018-05-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏猿人谷

memcpy和memmove的区别

memcpy()和memmove()都是C语言中的库函数,在头文件string.h中,其原型分别如下: void *memcpy(void *dst, con...

2285
来自专栏用户画像

H5 新增的input元素的类型

search类型用于搜索域,如站点搜索或Google搜索。search域显示为常规的文本域。

673
来自专栏UE4技术专场

UE4 ReplicationGraph分析

ReplicationDriverClassName="/Script/ProjectName.ClassName"

3712
来自专栏好好学习吧

vim简单使用教程

vim的学习曲线相当的大(参看各种文本编辑器的学习曲线),所以,如果你一开始看到的是一大堆VIM的命令分类,你一定会对这个编辑器失去兴趣的。下面的文章翻译自《L...

1313
来自专栏为数不多的Android技巧

ASCII Art:使用纯文本流程图

我们使用纯文本写代码,有了Markdown又可以使用纯文本写文档,那么对于更直观的信息表达方式——图片,能不能使用纯文本描述呢?

2022
来自专栏十月梦想

php代码之网站显示安全运行时间代码

上述就可实现网站计时功能,结合数组函数实现,后续可是使用js获取倒计时,时时显示!

982
来自专栏小李刀刀的专栏

在ASP中实现UNIX时间戳

  在康盛创想发布UC以后,我曾经尝试为其编写ASP把版本的客户端类库,过程中发现了几个问题,首当其冲的当然是服务器端不支持非php平台的接口,这个问题直接导致...

3936
来自专栏DOTNET

ASP.NET MVC编程——模型

1 ViewModel 是一种专门提供给View使用的模型,使用ViewModel的理由是实体或领域模型所包含的属性比View使用的多或少,这种情况下实体或领域...

3278
来自专栏小樱的经验随笔

Gym 100952A&&2015 HIAST Collegiate Programming Contest A. Who is the winner?【字符串,暴力】

A. Who is the winner? time limit per test:1 second memory limit per test:64 mega...

2736
来自专栏游戏杂谈

TexturePacker压缩png的命令

压缩png效果最好的当然是TinyPNG这种神器了,不过一般情况下TexturePacker压缩出来的也基本上能达到效果。

1552

扫码关注云+社区