CUDA-并行生成Halton序列
CUDA - Generating the Halton sequence in parallel
我想在CUDA中编写一个内核,该内核将并行生成Halton序列,每个线程生成并存储1个值。
从序列来看,生成序列中的每个后续值似乎都涉及到生成前一个值的工作。从头开始生成每个值将涉及冗余工作,并导致线程执行时间之间存在很大差距。
有没有任何方法可以通过改进串行算法的并行内核来实现这一点?我对并行编程真的很陌生,所以如果答案是一些众所周知的模式,请原谅这个问题。
注意:我确实在一本教科书中找到了这个链接(使用它时没有描述它的工作原理),但那里的文件链接已经死了。
Halton序列由以下生成:
- 求i在p进制中的表示
- 反转位顺序
例如,基于2的Halton序列:
index binary reversed result
1 1 1 1 / 10 = 1 / 2
2 10 01 01 / 100 = 1 / 4
3 11 11 11 / 100 = 3 / 4
4 100 001 001 / 1000 = 1 / 8
5 101 101 101 / 1000 = 5 / 8
6 110 011 011 / 1000 = 3 / 8
7 111 111 111 / 1000 = 7 / 8
因此,确实有很多反向的重复工作。我们能做的第一件事就是重用以前的结果。
当计算base-p Halton序列中索引为i的元素时,我们首先确定i的前导位和base-p表示的剩余部分(这可以通过以base-p方式调度线程来完成)。然后我们有
out[i] = out[remaining_part] + leading_bit / p^(length_of_i_in_base_p_representation - 1)
//"^" is used for convenience
为了避免不必要的全局内存读取,每个线程都应该处理具有相同"剩余部分"但不同"前导位"的所有元素。如果我们在p^n和p^(n+1)之间生成Halton序列,那么在概念上应该有p^n个并行任务。但是,如果我们为一个线程分配一组任务,则不会产生任何问题。
可以通过混合重新计算和从内存加载来进行进一步的优化。
示例代码:
线程总数应为p^m。
const int m = 3 //any value
__device__ void halton(float* out, int p, int N)
{
const int tid = ... //globally unique and continuous thread id
const int step = p^m; //you know what I mean
int w = step; //w is the weight of the leading bit
for(int n = m; n <= N; ++n) //n is the position of the leading bit
{
for(int r = tid; r < w; r += step) //r is the remaining part
for(int l = 1; l < p; ++l) //l is the leading bit
out[l*w + r] = out[r] + l/w;
w *= p;
}
}
注意:这个例子不计算Halton序列中的第一个p^m元素,但仍然需要这些值。
相关文章:
- 大量序列中核苷酸类型的快速计数
- 递归函数计算序列中的平方和(并输出过程)
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 从给定的 I 和 D 序列中形成最小数
- 如何在C++中序列化结构数据
- 具有最大子序列大小的序列,每个元素都相同
- 序列化,没有库的整数,得到奇怪的结果
- 算术序列与区间的最大重叠
- 将TPM公钥序列化为DER或PEM
- 算法问题:查找从堆栈中弹出的所有序列
- 使用FFMPEG将RGB图像序列保存到.mp4时出现问题
- 如何知道QDataStream不能反序列化某些内容
- 如何使用Python从C++中读取谷物序列化数据
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- 带有Protobuf序列化的C++Hazelcast:字符串不是UTF-8格式的
- 求最长递增子序列C++的长度
- 如何在文件中查找字节序列
- 自定义对象的dlib序列化在gcc中失败
- C++boost序列化多态性问题
- CUDA-并行生成Halton序列