展开循环以一次迭代 64 位、32 位

问题描述 投票:0回答:1

我在 32 位 Tensilica Xtensa DSP 微控制器上运行相对简单的 64 位重型算法,分析显示我们花费了很大一部分时间在两个 32 位 CPU 上执行基本的 64 位操作64 位变量的寄存器。

for(uint64_t bit = 1; bit; bit<<=1){
    if(bit & aGlobalBit){
         //Some light math
    } else {
        //different light math
    }
}

将上述伪代码稀疏展开两次,分别覆盖位索引 0->31 和 32->63,显示出很大的运行时加速。反汇编显示每个循环的指令数量大幅减少,因为 GCC12 发现每个循环只使用了 uint64_t 的一半:

//Do32LSBs
for(uint32_t bit = 1; bit; bit<<=1){
    if(bit & aGlobalBit){
         //Some light math
    } else {
        //different light math
    }
}
//Do32MSBs
for(uint32_t bitMsb = 1; bitMsb; bitMsb<<=1){
    uint64_t bit = (uint64_t)bitMsb << 32;
    if(bit & aGlobalBit){
         //Some light math
    } else {
        //different light math
    }
}

但我想找到一种更简洁的方法来做到这一点 - 迭代 uint64_t 中的位被大量使用,并且加速不值得维护循环体的两个副本。我已经阅读了 GCC 编译器手册中有关内联的部分,并且没有一个选项可以稀疏地执行此操作。如何抽象地包装位迭代,以便我可以编写一次并将其与 for-auto-x 一起使用?如果没有,是否有另一种方法可以从循环体中抽象迭代,同时仍然允许每个 uint64_t 一次进行 32 位迭代?

c++ loop-unrolling
1个回答
0
投票

老兄,这些只有 64 个值,只需将它们放入数组即可。它的大小为 512 字节,我相信您会在这个 MCU 资源中找到它们。

© www.soinside.com 2019 - 2024. All rights reserved.