有没有一种更快的方法来按位连接两个整数? < >我的C++程序,我想把两个32位无符号整数按位连接成一个64位无符号整数。类似的问题已经被问过多次,答案大多与此相似: #include <cstdint> #include <iostream> int main() { std::uint32_t leftHalf = 1; std::uint32_t rightHalf = 2; std::uint64_t concatenated = ((std::uint64_t) leftHalf << 32) | secondHalf; std::cout << "left=" << leftHalf << " and right=" << rightHalf << " concatenated into " << concatenated << std::endl; } #包括 #包括 int main() { std::uint32_t leftHalf=1; 标准:uint32_t rightshalf=2; std::uint64_t concatenated=((std::uint64_t)leftHalf

有没有一种更快的方法来按位连接两个整数? < >我的C++程序,我想把两个32位无符号整数按位连接成一个64位无符号整数。类似的问题已经被问过多次,答案大多与此相似: #include <cstdint> #include <iostream> int main() { std::uint32_t leftHalf = 1; std::uint32_t rightHalf = 2; std::uint64_t concatenated = ((std::uint64_t) leftHalf << 32) | secondHalf; std::cout << "left=" << leftHalf << " and right=" << rightHalf << " concatenated into " << concatenated << std::endl; } #包括 #包括 int main() { std::uint32_t leftHalf=1; 标准:uint32_t rightshalf=2; std::uint64_t concatenated=((std::uint64_t)leftHalf,c++,performance,bitwise-operators,C++,Performance,Bitwise Operators,如果找到一种有效的方法将一个值的一部分(视为位集)复制到另一个值的一部分(视为位集),则可以额外提高速度。但我想这可能有点不太方便 顺便说一下,在下面的代码中,函数concat1在编译代码中比concat2短一个命令 #include <iostream> using namespace std; std::uint64_t concat1(const std::uint32_t& leftHalf, const std::uint32_t& rightHalf){

如果找到一种有效的方法将一个值的一部分(视为位集)复制到另一个值的一部分(视为位集),则可以额外提高速度。但我想这可能有点不太方便

顺便说一下,在下面的代码中,函数
concat1
在编译代码中比
concat2
短一个命令

#include <iostream>
using namespace std;

std::uint64_t concat1(const std::uint32_t& leftHalf, const std::uint32_t& rightHalf){
    std::uint64_t concatenated = leftHalf;
    concatenated <<= 32;
    concatenated |= rightHalf;
    
    return concatenated;
}

std::uint64_t concat2(const std::uint32_t& leftHalf, const std::uint32_t& rightHalf){
    std::uint64_t concatenated = (static_cast<std::uint64_t>(leftHalf) << 32) | rightHalf;
    
    return concatenated;
}

int main() {
    cout << concat1(1,2) <<std::endl;
    cout << concat2(1,2) <<std::endl;
}

如果你能找到一种有效的方法,将一个值的一部分(视为位集)复制到另一个值的一部分(视为位集)中,你可以额外提高速度。但我想这可能有点不妥

顺便说一下,在下面的代码中,函数
concat1
在编译代码中比
concat2
短一个命令

#include <iostream>
using namespace std;

std::uint64_t concat1(const std::uint32_t& leftHalf, const std::uint32_t& rightHalf){
    std::uint64_t concatenated = leftHalf;
    concatenated <<= 32;
    concatenated |= rightHalf;
    
    return concatenated;
}

std::uint64_t concat2(const std::uint32_t& leftHalf, const std::uint32_t& rightHalf){
    std::uint64_t concatenated = (static_cast<std::uint64_t>(leftHalf) << 32) | rightHalf;
    
    return concatenated;
}

int main() {
    cout << concat1(1,2) <<std::endl;
    cout << concat2(1,2) <<std::endl;
}

综合这些信息,可以得出原始问题的以下答案:

这要视情况而定。而且,更快的方式很可能不会有什么不同。 根据周围的代码,可以使用以下技术:

  • 可以将32位部分存储为数组中的两个元素,然后将该数组
    memcpy
    存储为64位整数。()
  • 根据32位值的存储方式,可以使用并行化,例如使用AVX命令()
但这可能没什么区别 其他操作(如从内存/缓存中单次提取数据)比多个逐位操作()需要更多的运行时间。因此,在当前CPU设计中,逐位操作可能在加载操作期间运行,下一条指令等待耗时的加载操作完成


最后,强烈建议使用一种方法(例如,
gcc-S
,一种探查器,如perf)来确定代码的哪些部分花费的时间最多。

这些信息的组合将导致以下原始问题的答案:

这要视情况而定。而且,更快的方式很可能不会有什么不同。 根据周围的代码,可以使用以下技术:

  • 可以将32位部分存储为数组中的两个元素,然后将该数组
    memcpy
    存储为64位整数。()
  • 根据32位值的存储方式,可以使用并行化,例如使用AVX命令()
但这可能没什么区别 其他操作(如从内存/缓存中单次提取数据)比多个逐位操作()需要更多的运行时间。因此,在当前CPU设计中,逐位操作可能在加载操作期间运行,下一条指令等待耗时的加载操作完成


最后,强烈建议使用一种方法(例如,
gcc-S
,一个探查器,如perf)来确定代码的哪些部分花费的时间最多。

对gcc和CLANG使用
-O2
-O3
进行了尝试,两种编译器的结果都是相同的(GCC和CLANG-
sal
shl
和指令顺序之间存在细微差异)。即使使用选项-O2和-O3,concat2也少了一个mov操作。@UweJ,它们在Clang trunk上都给出了相同的asm:。通过值而不是引用传递可以节省一条额外的指令/两个指针取消引用:。GCC trunk给出了非常相似的结果。@chris和Brendan。感谢您的努力!我只尝试了一个GCC编译器。编译器的优化功能显然比我在代码上尝试的微优化有更大的影响。因此,我的尝试就是一个例子,说明为什么在许多(可能是大多数)代码中应该避免微优化案例。对GCC和CLANG使用
-O2
-O3
进行了尝试,两种编译器的结果都是相同的(GCC和CLANG-
sal
shl
和指令顺序之间存在细微差异)。即使使用选项-O2和-O3,concat2也少了一个mov操作。@UweJ,它们在Clang trunk上都给出了相同的asm:。通过值而不是引用传递可以节省一条额外的指令/两个指针取消引用:。GCC trunk给出了非常相似的结果。@chris和Brendan。感谢您的努力!我只尝试了一个GCC编译器。编译器的优化功能显然比我在代码上尝试的微优化有更大的影响。因此,我的尝试就是一个例子,说明为什么在许多(可能是大多数)代码中应该避免微优化案例。注释不用于扩展讨论;本次对话已经进行过。只需确保不会落入典型的优化陷阱。首先证明这是一个瓶颈。如果是,请首先尝试调整算法,以避免执行此操作。此操作极不可能是您的瓶颈。注释为not用于扩展讨论;本次对话已经结束。请确保不要落入典型的优化陷阱。首先证明这是一个瓶颈。如果是,请首先尝试并调整您的算法,以避免执行此操作。此操作极不可能是您的瓶颈。
concat1(unsigned int const&, unsigned int const&):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-24], rdi
        mov     QWORD PTR [rbp-32], rsi
        mov     rax, QWORD PTR [rbp-24]
        mov     eax, DWORD PTR [rax]
        mov     eax, eax
        mov     QWORD PTR [rbp-8], rax
        sal     QWORD PTR [rbp-8], 32
        mov     rax, QWORD PTR [rbp-32]
        mov     eax, DWORD PTR [rax]
        mov     eax, eax
        or      QWORD PTR [rbp-8], rax
        mov     rax, QWORD PTR [rbp-8]
        pop     rbp
        ret
concat2(unsigned int const&, unsigned int const&):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-24], rdi
        mov     QWORD PTR [rbp-32], rsi
        mov     rax, QWORD PTR [rbp-24]
        mov     eax, DWORD PTR [rax]
        mov     eax, eax
        sal     rax, 32
        mov     rdx, rax
        mov     rax, QWORD PTR [rbp-32]
        mov     eax, DWORD PTR [rax]
        mov     eax, eax
        or      rax, rdx
        mov     QWORD PTR [rbp-8], rax
        mov     rax, QWORD PTR [rbp-8]
        pop     rbp
        ret