2017-04-08 60 views
-1

A C++标准库用下面的代码(忽略各种包装和概念支票等的)与简单的循环实现std::copy通用翘曲级的std ::复制般的功能 - 什么是应该考虑?

for (; __first != __last; ++__result, ++__first) 
    *__result = *__first; 

现在,假设我想的通用为经线std::copy样函数(未块;不栅极)以用于协作从一个地方将数据复制到另一个。为了简单起见,我们甚至假设函数使用指针而不是任意的迭代器。

当然,在CUDA中编写通用代码通常是一种无用的追求 - 因为我们可能首先牺牲了使用GPU的许多优势,以支持通用性 - 所以我会允许我自己布尔/枚举模板参数以可能频繁出现的情况之间选择,避免运行时检查。所以签名可能是,说:

template <typename T, bool SomeOption, my_enum_t AnotherOption> 
T* copy(
    T*  __restrict__ destination, 
    const T* __restrict__ source, 
    size_t     length 
); 

但对于每一种情况下我的目标以获得最佳性能(或因为我们不知道还有什么其他的经纱在做最佳预期的性能)。

写这样的功能时,我应该采取哪些因素考虑?或者换句话说:我应该在实施这个功能时区分哪些情况?

注:

  • 这应该针对计算能力3.0或更高(即开普勒或更新微架构)
  • 我不想做一个运行时API调用memcpy()。至少,我不认为我这样做。
+1

不此[存在](https://nvlabs.github.io/cub/group___u til_io.html)? – talonmies

+0

@talonmies:我不这么认为;那些CUB功能/方法用于将数据加载到分解/展开/条纹/等等。形式。其中一些是块级的。但是,我认为这是一个很好的去寻找灵感的地方。 – einpoklum

回答

-1

因素我认为应该考虑到:

  • 聚结内存写入 - 确保一经写入连续的内存位置(无缺口),其连续的车道。
  • 型式尺寸VS存储器事务大小我 - 如果sizeof(T)sizeof(T)是为1或2,且我们有具有各车道写一个单一的元件,整个经纱会写小于128B,浪费了一些存储器事务的。相反,我们应该让每个线程将2或4个输入元素放置在一个寄存器中,并且写入
  • 类型大小vs内存事务大小II - 对于lcm(4,sizeof(T))> 4的类型大小,它不是很完美明确要做什么。当每个通道写入超过4个字节时,编译器/ GPU处理写入的效果如何?我在想。
  • 由于一次读取多个元素造成的延迟 - 如果每个线程希望为每个写入读取2或4个元素,并写入4个字节的整数 - 我们可能在开始处有1个或2个元素,必须单独处理输入的结尾。
  • 松弛由于输入地址未对准 - 输入在32B交易被读取(以及,它应该是 - 编译器应该优化访问该方式);因此,我们必须以不同方式处理的第一要素高达32B的多,最后元素(在最后这种多)。
  • 由于输出地址错误对齐导致Slack错误 - 在128B个事务中读取输出;因此我们必须以不同的方式处理128B倍数的第一个元素和最后一个元素(在最后一个这样的倍数之后)。
  • T是不是可复制构造的。但让我们假设它是。

但可能是我错过了一些注意事项,或者上面的一些是多余的。

因素我一直都在怀疑:

  • 块大小(即其他经线究竟有多少)
  • 的计算能力(因为它至少3)
  • 无论源/目标是在共享存储器/常量存储器
  • 的高速缓存模式选择
相关问题