繁体   English   中英

优化寄存器/ L1中数据的每线程复制和0填充

[英]Optimizing per-thread copying and 0-padding of data in registers/L1

我正在编写一个内核,该内核除其他外,使每个线程用构成低字节的数据填充一个变量,并填充其余变量(假定为低端字节序)。 这是在线程之间重复且不一致地完成的,因为某些线程可能有更多字节要复制到其变量中,而填充较少,而某些线程要复制而更少并具有更多的填充。 结果和未填充的数据都位于寄存器中(用于较小的大小),共享存储器中或本地存储器中(应由L1覆盖)。

换句话说,假设每个线程都执行:

T padded;
pad_high_bytes(padded, my_low_bytes, my_num_low_bytes);
do_stuff(padded);

我们在哪里:

template <typename T>
__device__ __forceinline__
void pad_high_bytes(
    T&                                result,
    const unsigned char* __restrict__ low_bytes, 
    unsigned                          num_low_bytes);

如果T大(例如struct { int data[50]; } ),那么我想我应该只使用CUDA的设备代码memcpy() 但是,通常情况并非如此-T通常为4或8,低字节数通常在1到3之间,甚至0也并不罕见。

我显然可以遍历字节,并希望达到最佳效果。 只要还有4个以上的字节需要复制,我还可以“循环遍历int”,然后循环遍历其余字节。 但:

  1. 我可以做得更好吗?
  2. 我应该以某种方式说明对齐方式吗? 还是麻烦太多了?
  3. 复制和填充应该在代码中完全分开还是应该以某种方式将它们组合在一起?
  4. 切换到memcpy()的sizeof(T)的合理值是多少-如果有的话?

请记住,该函数是在结果类型上模板化的,因此,如果您只想说较小的或较大的T,那会很有帮助。

我真的很努力地看待Q1-3,这可以被解释为“我的话语是对这个模糊描述的任务的最佳设计”,如何真正地负责。 所以我什至不尝试。

Q4 负责任的:

设备端memcpy (或设备端cudaMemcpy ,它只是memcpy一个薄包装)总是发出一个执行逐字节复制循环 当您知道要在编译时复制的类型的大小时, 总是可以自己编写一个复制循环来做得更好,该循环利用有关该类型大小的先验知识(受对齐约束等)的影响。 而且,如果您既知道类型的大小,又知道要复制的单词数,那么除了进行比字节大小的事务外,还可以利用循环展开来做得更好

如果您不知道这两件事中的任何一个,那么memcpy仍然是最好的选择,因为它可以简化代码,并且可以在工具链中进行惯用的优化。 我唯一不建议这样做的是,如果您有机会将其他操作与副本融合在一起,在这种情况下,自己做些事还是很有意义的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM