Algorithm 臂组件的PRNG?

Algorithm 臂组件的PRNG?,algorithm,assembly,random,arm,Algorithm,Assembly,Random,Arm,我在为手臂装配实现PRNG时遇到问题。我尝试过一些算法,在工作时,在最初的几次随机数迭代之后需要很长时间,可能是因为除法(模)步骤在大数上需要很长时间。我试图得到一个介于0和31之间的随机数。我在下面给出了我的粗略工作,用信件代替了特定的登记簿 开始: mov t, x // t = x // t ^= t << 11 lsl temp, t, #11 eor t, temp // t ^= t >> 8 lsr temp, t, #8 eor

我在为手臂装配实现PRNG时遇到问题。我尝试过一些算法,在工作时,在最初的几次随机数迭代之后需要很长时间,可能是因为除法(模)步骤在大数上需要很长时间。我试图得到一个介于0和31之间的随机数。我在下面给出了我的粗略工作,用信件代替了特定的登记簿

开始:

mov t, x            // t = x

// t ^= t << 11
lsl temp, t, #11
eor t, temp

// t ^= t >> 8
lsr temp, t, #8
eor t, temp

// z = w
mov z, w

// x = y
mov x, y

// y = z
mov y, z

// w ^= w >> 19
lsr temp, w, #19
eor w, temp

// w ^= t
eor w, t

// result is the RETURNED RANDOM NUMBER
mov result, w
movt,x//t=x
//t^=t>8
lsr温度,t,#8
三次采油温度
//z=w
莫夫z,w
//x=y
mov x,y
//y=z
莫夫y,z
//w^=w>>19
lsr温度,w,#19
提高采收率,温度
//w^=t
提高采收率w,t
//结果是返回的随机数
mov结果,w
这是我在维基百科的XORSHIFT页面上尝试实现的算法。我只需要返回一个从0到31的随机数,所以对一个10位数字进行除法需要一段时间,而且似乎有点过头了。如果有人能帮我优化或指出错误,我将不胜感激

编辑:上面的子例程返回随机数,然后我基本上将它除以31(这里没有给出代码),并将余数作为从0到31的“随机”数

ARM指令,因此使用单独的左移位指令是一种浪费。显然

请注意,如果您的例程是您实际调用的函数,而不仅仅是来自循环的内联代码段,那么它就不符合标准ABI。如果唯一的调用方也是由您在asm中编写的,那么这很好。若您可以将4个寄存器专用于循环中的PRNG状态,那个么您就不需要传递指针或加载/存储

一如既往,这通常是一个很好的起点:

// we need a loop to see how many mov instructions are actually needed when keeping state in regs
// Otherwise we just get loads/stores
uint32_t xorshift_loop(uint32_t *output, uint32_t x, uint32_t y, uint32_t z, uint32_t w) {
  for(int i=0 ; i<1000 ; ++i) {
    uint32_t t = x;
    t ^= t << 11;
    t ^= t >> 8;
    x = y; y = z; z = w;
    w ^= w >> 19;
    w ^= t;
    *(++output) = w;
  }
  return w;
}
请注意XOR是如何重新排序的,因此前几条指令是独立dep链的一部分。这将有助于ARM内核的超标量排序,或者如果移位操作数的
eor
延迟大于1。它还选择做
w^=t;w^=t>>8
而不是
t^=t>>8;w^=t,但如果有任何特殊的优势,请拨打IDK

两次展开将删除所有
mov
指令,使每个迭代只执行四条
eor
指令,每个结果的输入都会发生移位。它看起来像带有
-funroll循环的gcc,以8展开,因此代码很难理解


为了这么快的东西


它在AArch64上编译成短代码,在32位ARM上仍然编译成短/高效的代码。不过,代码远不止xorshift。请参阅上面的“我的godbolt编译器浏览器”链接

您的分区错误;它应该是“除以32”以得到31的可能余数。但“模32”只是“和31”,保留较低的5位。啊,使用和31可以大大缩短时间。非常感谢。谢谢你的深入回答!在线移位/旋转使我的代码更加清晰。回答得很好。
## 32bit ARM gcc 4.8  -O3 -fverbose-asm
## The @comments are from -fverbose-asm, which is more helpful than usual here
.L4:
        eor     r6, r1, r1, lsl #11       @, t, x, x,
        eor     r5, r4, r4, lsr #19       @, w, w, w,
        eors    r5, r5, r6                @, t, w, t
        mov     r1, r2                    @ x, y
        eor     r5, r5, r6, lsr #8        @, w, t, t,
        str     r5, [r0, #4]!     @ w, MEM[base: _42, offset: 4B]  // this is a post-increment store
        cmp     r0, r7    @ ivtmp.20, D.4237
        mov     r2, r3    @ y, z
        mov     r3, r4    @ z, w
        mov     r4, r5    @ w, w
        bne     .L4       @,