[英]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”,然后循环遍历其余字节。 但:
请记住,该函数是在结果类型上模板化的,因此,如果您只想说较小的或较大的T,那会很有帮助。
我真的很努力地看待Q1-3,这可以被解释为“我的话语是对这个模糊描述的任务的最佳设计”,如何真正地负责。 所以我什至不尝试。
Q4 是负责任的:
设备端memcpy
(或设备端cudaMemcpy
,它只是memcpy
一个薄包装)总是发出一个执行逐字节复制的循环 。 当您知道要在编译时复制的类型的大小时, 总是可以自己编写一个复制循环来做得更好,该循环利用有关该类型大小的先验知识(受对齐约束等)的影响。 而且,如果您既知道类型的大小,又知道要复制的单词数,那么除了进行比字节大小的事务外,还可以利用循环展开来做得更好
如果您不知道这两件事中的任何一个,那么memcpy
仍然是最好的选择,因为它可以简化代码,并且可以在工具链中进行惯用的优化。 我唯一不建议这样做的是,如果您有机会将其他操作与副本融合在一起,在这种情况下,自己做些事还是很有意义的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.