根据大多数NVidia文档,CUDA核心是标量处理器,应该只执行标量操作,这将被矢量化到32组件的SIMT翘曲。
但是OpenCL有向量类型,例如,uchar8.It的大小与ulong (64位)相同,可以由单个标量核处理。如果我对一个uchar8向量进行操作(例如,组件级的加法),这也会映射到单个核上的指令吗?
如果一个块(工作组)中有1024个工作项,并且每个工作项处理一个uchar8,这会有效地并行处理8120 uchar吗?
编辑:我的问题是,在CUDA体系结构上(独立于OpenCL),是否有一些矢量指令在“标量”核中可用。因为如果内核已经能够处理32位类型,那么它也可以处理32位uchar4的添加是合理的,特别是因为矢量操作经常用于计算机图形学。
发布于 2018-01-19 16:45:50
CUDA具有“内建”(即预定义)向量类型,4字节数量(如int4)的大小可达4,8字节数量(如double2)的大小可达2。CUDA线程的最大读/写事务大小为16字节,因此这些特定大小的选择往往与最高值一致。
它们被公开为典型的结构,因此您可以引用例如.x来访问向量类型的第一个元素。
与OpenCL不同,CUDA不为基本算术(如+、-等)提供内置操作(“重载”),用于这些向量类型的元素级操作。没有什么特别的原因,你不能提供这样的超载自己。同样,如果您想要一个uchar8,您可以很容易地为它提供一个结构定义,以及任何想要的操作符重载。这些实现可能就像您对普通C++代码所期望的那样。
那么,一个潜在的问题可能是,在这方面,数据自动化系统和OpenCL在实施方面有什么不同?如果我在uchar8上做手术,例如。
uchar8 v1 = {...};
uchar8 v2 = {...};
uchar8 r = v1 + v2;OpenCL和CUDA在机器性能(或低级代码生成)方面有什么不同?
对一个有数据自动化系统能力的GPU来说可能不算什么。CUDA核心(即底层ALU)对uchar8上的此类操作没有直接的本机支持,而且,如果您编写了自己的符合C++的重载,您可能会使用C++语义来实现这一本质上的串行操作:
r.x = v1.x + v2.x;
r.y = v1.y + v2.y;
...因此,这将分解为在CUDA核心上执行的操作序列(或在CUDA SM中的适当整数单元中)。由于NVIDIA硬件不为单核/时钟/指令中的8路uchar添加提供任何直接支持,因此OpenCL (在NVIDIA上实现)的方式也不可能大不相同。在较低的级别上,底层机器代码将是一系列操作,而不是一条指令。
顺便说一下,CUDA (或PTX,或CUDA本质)确实在单个核心/线程/指令中提供了有限数量的向量操作。这方面的一些例子是:
half2向量类型和更高的GPU本地支持16位浮点。即使使用智能OpenCL编译器可以将某些向量操作映射到硬件“本机支持”的各种操作中,它也不会完全覆盖。在单个核心/线程上,在一条指令中,没有对8宽矢量(例如uchar8)的操作支持来选择一个例子。所以有些序列化是必要的。实际上,我不认为NVIDIA的OpenCL编译器那么聪明,所以我的期望是,如果您研究机器代码,您会发现这种每线程向量操作都是完全序列化的。
在CUDA中,您可以为某些操作和向量类型提供自己的过载,这些操作和向量类型可以在一条指令中表示。例如,uchar4添加可以使用vadd4()内禀“本地”执行(可能包括在操作符重载的实现中)。同样,如果您正在编写自己的操作符重载,我认为使用两个uchar8指令执行__vadd4()元素向量添加并不困难。
发布于 2018-01-19 16:19:01
如果我对一个uchar8向量进行操作(例如,组件级的加法),这也会映射到单个核上的指令吗?
AFAIK --它总是在一个核心上(来自单个内核/工作项的指令不跨核,除了特殊的指令(比如屏障)),但它可能不止一个指令。这取决于硬件是否支持uchar8上的操作。如果不这样做,那么uchar8将被分解成所需的多个片段,并且每个片段将被单独的指令处理。
OpenCL是非常“通用”的,因为它支持许多不同的向量类型/大小组合,但是现实世界的硬件通常只实现一些向量类型/大小组合。您可以查询OpenCL设备的“首选向量大小”,这将告诉您该硬件最有效的是什么。
https://stackoverflow.com/questions/48345049
复制相似问题