假设我有一个64位无符号整数(u64)tasks
,并且设置了一个或多个位。
我想从project.tasks.getByName("tasks").doFirst {
println "do something before task [tasks] executes"
}
中随机选择一个设置位,以给出一个新的掩码mask
,以便m
设置一个位。一些伪代码可以做到这一点:
x
但是,我需要尽可能快地执行此操作(与上述类似的低级语言代码正在减慢热循环的速度)。有人有更有效的方案吗?
答案 0 :(得分:4)
如何对此进行优化的细节取决于您未指定的几个因素-目标体系结构,掩码中设置位的预期数量,要使用的语言,对随机性的要求等等。在不知道更多细节的情况下,很难给出有用的答案,但是我会给出一些可能仍然有用的提示。
大多数现代体系结构都有一条指令,用于对整数(通常称为“ popcount”)中设置的位数进行计数,并且该指令以大多数低级语言公开。在Rust中,您可以使用count_ones()
method。这样一来,您就可以从k
位的总数中进行选择。
然后,您可以在i
和0
(含)之间生成一个随机数k - 1
。下一步是选择i
中的第mask
位。一个有效的方法是以下循环(Rust代码):
for _ in 0..i {
mask &= mask - 1;
}
let new_mask = 1 << mask.trailing_zeros();
循环将在每次迭代中清除最低有效位。自i < k
起,我们知道循环后mask
不能为零。最后一行从仍设置的mask
的最低有效位生成新的掩码。
在常见的体系结构上,瓶颈可能是随机数生成器。如果您使用的是Rust的rand
板条箱,则可以使用SmallRng
来提高性能,但要以加密不安全为代价,这可能与您的用例无关。