Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将随机整数转换为范围[min,max],无需分支_C++_Bit Manipulation_Simd_Avx2 - Fatal编程技术网

C++ 将随机整数转换为范围[min,max],无需分支

C++ 将随机整数转换为范围[min,max],无需分支,c++,bit-manipulation,simd,avx2,C++,Bit Manipulation,Simd,Avx2,我得到了一个生成随机字节数组的方法。它是C++的均匀分布和STD文库的MeSouthWistor的6倍。 数组的计数可以被4整除,因此可以将其解释为整数数组。将每个条目转换为整数,将生成范围为[INT\u MIN,INT\u MAX]的值。但是如何将这些整数值转换为介于我自己的[min,max]之间的值呢 我想避免任何if-else,以避免分支 也许我应该应用一些位逻辑,在每个数字中丢弃不相关的位?(因为所有剩余的未屏蔽位都将是0或1)。如果我可以提取最大值中的最高有效位,我可以在整数中屏蔽任

我得到了一个生成随机字节数组的方法。它是C++的均匀分布和STD文库的MeSouthWistor的6倍。

数组的计数可以被4整除,因此可以将其解释为整数数组。将每个条目转换为整数,将生成范围为
[INT\u MIN,INT\u MAX]
的值。但是如何将这些整数值转换为介于我自己的
[min,max]
之间的值呢

我想避免任何if-else,以避免分支


也许我应该应用一些位逻辑,在每个数字中丢弃不相关的位?(因为所有剩余的未屏蔽位都将是0或1)。如果我可以提取最大值中的最高有效位,我可以在整数中屏蔽任何比该位更重要的位

例如,如果我希望我的
max
为17,则它是二进制形式的
0000001
。也许我的面具会看起来像
0001111
?然后我可以将其应用于数组中的所有数字

但是,这个掩码是错误的……它实际上允许的值最多为
(1+2+4+8+16)
:(

我能做什么?还有,如何处理
min

编辑


我在我的应用程序的每一帧都生成数百万个数字,用于神经网络。我设法使用AXV2对浮点变量(使用),但也需要使整数工作。

核心思想是使用模而不是按位掩码,这在非2次幂的情况下是无用的。无分支也是一个有点奇怪的要求。你想要的是“足够快”,而不是“无分支和按位掩码”

假设我们有一个函数

int rand();
如果
max
的形式为
2^n-1
,则

rand()%(最大值+1)
将统一生成一个范围为
[0,max]
的随机整数。这是因为整数的总数是2的幂

现在,如果
min
max
max-min
的形式
2^n-1
,那么

(rand()%(最大最小值+1))+min
将统一生成范围
[min,max]
内的随机整数

但是当
max-min
不是
2^n-1
的形式时会发生什么?那么我们就倒霉了。
(rand()%(max-min+1))+min
方法仍然会在
[min,max]中生成一个随机整数
范围,但不再是一致的。这是为什么?因为当
n
是固定的,而不是2的幂,那么给出具体
r=x%n
结果的整数总数根据
r
而变化

然而,这种方法并不坏。越大的
max-min
值越接近均匀分布,在实践中通常就足够好了。而且它非常快,没有分支

另一个例子是

upper=get_upper_power_of_2(max-min)
做
{
tmp=rand()%上限;
}而(tmp>max-min);
结果=tmp+min;
该方法具有很好的一致性,但它没有停止特性,即理论上该算法可能永远不会停止。它也有分支。但在实践中,它停止得非常快(概率很大),因此它是非常常见的算法。例如,它在标准Java库中

当然,当
max-min
溢出时(即
min
是一个很大的负数时),这两种方法都有一个问题,如果我们切换到无符号整数,然后返回整数,这个问题就可以解决

据我所知,
[0,max]中没有生成随机整数的算法
max
不是
2^n-1
来自
01
统一生成器的形式时,结果是统一的,并且具有停止特性。我认为不可能存在这样的算法,但我在计算机科学中找不到合适的结果

但是如何将这些整数值转换为介于我自己的
[min,max]
之间的值呢

由于范围可能不是2的幂,所以位屏蔽已被禁用,但您已经发现了这一点

模也不存在,它在AVX2中不作为本机操作存在(即使存在,也不一定会使其有效)

还有另一种选择:使用
\u mm256\u mul\u epu32
(不幸的是,32位数字没有像16位数字那样的“纯”乘法高,因此我们只能执行50%有用的操作)。其想法是获取输入数字
x
(全范围)和所需的范围
r
,然后计算
r*x/2^32
,其中除法是隐式的(通过取乘积的高半部来实现)

x/2^32
如果被解释为一个有理数,那么它应该是[0.0..1.0]中的一个数字(不包括1.0),乘以
r
,然后将范围扩大到[0.0..
r
)(不包括
r
)。这不是它的计算方式,但这是公式的来源

通过将
min
添加到缩放结果中,可以轻松设置范围的最小值

在代码中(经过轻微测试):

它仍然是一个独占范围,无法将完整的
[INT\u MIN..INT\u MAX]
作为输出范围处理。甚至无法指定它,它最多只能
[INT\u MIN..INT\u MAX)
(或者例如,具有零偏移量的等效范围:
[0..-1)


它也不是真正统一的,因为同样的原因,简单的基于模的范围缩减不是真正统一的,你不能公平地将
N
大理石除以
K
箱子,除非
K
恰好将
N
平均分割。

如果一个值中有2^N个随机位,你可以通过do将其放入一个整数范围ing:

r=((值*(最大-最小值)
__m256i squish(__m256i x, int min, int max) {
    __m256i sizeOfRange = _mm256_set1_epi32((unsigned)max - min);
    __m256i scaled_even = _mm256_shuffle_epi32(_mm256_mul_epu32(x, sizeOfRange), 0xB1);
    __m256i scaled_odd = _mm256_mul_epu32(_mm256_shuffle_epi32(x, 0xB1), sizeOfRange);
    __m256i scaled = _mm256_blend_epi32(scaled_even, scaled_odd, 0xAA);
    return _mm256_add_epi32(scaled, _mm256_set1_epi32(min));
}
r = _mm256_add_epi16(
      _mm256_mulhi_epi16(value, _mm256_set1_epi16(max-min)), 
    _mm256_set1_epi16(min));