Optimization 一个通用的warp-level std::copy-like函数-它应该解释什么? 一个C++标准库使用以下代码实现代码< > STD::复制< /代码>(忽略各种包装和概念检查等):简单循环: for (; __first != __last; ++__result, ++__first) *__result = *__first;

Optimization 一个通用的warp-level std::copy-like函数-它应该解释什么? 一个C++标准库使用以下代码实现代码< > STD::复制< /代码>(忽略各种包装和概念检查等):简单循环: for (; __first != __last; ++__result, ++__first) *__result = *__first;,optimization,cuda,gpgpu,stl-algorithm,Optimization,Cuda,Gpgpu,Stl Algorithm,现在,假设我想要一个通用的std::copy-like函数,用于将数据从一个地方协作复制到另一个地方。为了简单起见,我们甚至假设函数采用指针而不是任意迭代器 当然,在CUDA中编写通用代码通常是一个无用的追求——因为我们可能会牺牲大量使用GPU的好处,而支持通用性——因此我将允许自己使用一些布尔/枚举模板参数,以便在频繁发生的情况之间进行选择,从而避免运行时检查。所以签名可能是,比如: template <typename T, bool SomeOption, my_enum_t Ano

现在,假设我想要一个通用的
std::copy
-like函数,用于将数据从一个地方协作复制到另一个地方。为了简单起见,我们甚至假设函数采用指针而不是任意迭代器

当然,在CUDA中编写通用代码通常是一个无用的追求——因为我们可能会牺牲大量使用GPU的好处,而支持通用性——因此我将允许自己使用一些布尔/枚举模板参数,以便在频繁发生的情况之间进行选择,从而避免运行时检查。所以签名可能是,比如:

template <typename T, bool SomeOption, my_enum_t AnotherOption>
T* copy(
    T*        __restrict__  destination, 
    const T*  __restrict__  source,
    size_t                  length
); 
模板
复印件(
T*\uuuu限制\uuuu目的地,
常数T*\uuuu限制\uuuu源,
尺寸和长度
); 
但对于每一种情况,我的目标都是获得最佳性能(或者在我们不知道其他翘曲在做什么的情况下获得最佳预期性能)

在编写这样一个函数时,我应该考虑哪些因素?或者换句话说:在实现此功能时,我应该区分哪些情况

注意事项:

  • 这应针对3.0或更高版本的计算能力(即开普勒或更新的微体系结构)
  • 我不想进行运行时API
    memcpy()
    调用。至少,我想我不知道

我认为应该考虑的因素:

  • 合并内存写入-确保扭曲中的连续通道写入到连续内存位置(无间隙)
  • 类型大小vs内存事务大小I-如果
    sizeof(T)
    sizeof(T)
    为1或2,并且我们让每个通道写入单个元素,则整个扭曲将写入小于128B的数据,从而浪费一些内存事务。相反,我们应该让每个线程在寄存器中放置2或4个输入元素,并将其写入
  • 类型大小与内存事务大小II-对于lcm(4,
    sizeof(T)
    )>4这样的类型大小,不太清楚该怎么做。当每个通道写入超过4个字节时,编译器/GPU处理写入的效果如何?我想知道
  • 由于一次读取多个元素而导致的松弛-如果每个线程希望为每次写入读取2或4个元素,并写入4字节整数,则在输入的开头和结尾可能有1或2个元素,必须单独处理
  • 由于输入地址不一致而导致的松弛-输入在32B事务中读取(在合理假设下);因此,我们必须以32B的倍数处理第一个元素,而以不同方式处理最后一个元素(在最后一个这样的倍数之后)
  • 由于输出地址错误对齐而导致的松弛-输出写入高达128B的事务中(或者仅32B?);因此,我们必须以这个数字的倍数来处理第一个元素,而以不同的方式处理最后一个元素(在最后一个倍数之后)
  • 是否
    T
    是可复制的
    。但我们假设是这样
但可能是我遗漏了一些考虑因素,或者上面的一些是多余的

我一直想知道的因素有:

  • 块大小(即有多少其他扭曲)
  • 计算能力(假设至少为3)
  • 源/目标是否在共享内存/常量内存中
  • 缓存模式的选择

这不是吗?@talonmes:我不这么认为;这些CUB函数/方法用于将数据加载到分解/展开/条带化等形式。其中一些是块级的。但我想这是一个获得灵感的好地方。