C++ 将4个字节扩展为8个字节的最快方式(32位->;64位)

C++ 将4个字节扩展为8个字节的最快方式(32位->;64位),c++,c,performance,low-level-code,C++,C,Performance,Low Level Code,假设您有一个32位无符号整数,其中字节的组织方式如下:abcd。 以这种方式将这些字节扩展为64位无符号整数的最快方法是什么: 0a0b0c0d?它适用于x86-64体系结构。我想知道不使用特殊内在函数的最快方法,尽管这也很有趣。 (我说“最快”,但性能合理的紧凑型解决方案也不错) 为需要上下文的人编辑。这似乎是一项非常简单的工作,只需移动一些字节,但它需要比您想象的更多的指令()。因此,我想知道是否有人知道一种方法可以用更少的指令来解决这个问题。类似的东西 uint64_t x = ...;

假设您有一个32位无符号整数,其中字节的组织方式如下:
abcd
。 以这种方式将这些字节扩展为64位无符号整数的最快方法是什么:
0a0b0c0d
?它适用于
x86-64
体系结构。我想知道不使用特殊内在函数的最快方法,尽管这也很有趣。 (我说“最快”,但性能合理的紧凑型解决方案也不错)

为需要上下文的人编辑。这似乎是一项非常简单的工作,只需移动一些字节,但它需要比您想象的更多的指令()。因此,我想知道是否有人知道一种方法可以用更少的指令来解决这个问题。

类似的东西

uint64_t x = ...;
// 0 0 0 0 a b c d
x |= x << 16;
// 0 0 a b ? ? c d
x = x << 8 & 0x00ff000000ff0000 | x & 0x000000ff000000ff;
// 0 a 0 b 0 c 0 d
_mm256_cvtepu8_epi16(八位数字):获取十六个八位数字的128位向量,并将其转换为十六个十六位有符号整数的256位向量。例如:

 __m128i value1 = _mm_setr_epi8(0x11, 0x22, 0x33, 0x44, 
    0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00);
 __m256i value2 = _mm256_cvtepu8_epi16(value1);
或对于32位->64位:


可能只是一点点移动,然后将它们异或在一起您尝试过什么-请将您最好的代码编辑到您的问题中,并在
性能标签中解释为什么您认为它不是您所需要的:“用于与代码和应用程序效率的度量或改进有关的问题。”你还没有什么需要衡量或改进的。除非你有什么东西,否则任何东西都是最快的。闻起来像是过早的优化。请显示您的代码这适用于16位到32位的扩展:
((x*0x0101010101010101L和0x80402010040201L)*0x0102040810204081L>>49)和0x5555
。摘自。选择您最喜欢的内容,但要考虑到在x86_64上,更少的指令并不一定意味着更快的执行时间。我喜欢它!与我在问题中提供的godbolt相比,它更短,并且节省了3个操作。难道_pdep_u64(x,0xff00ff00ff00ff)不只是在指定的位置传递位吗?它有32位输入和32位输出。我所发现的唯一可以执行所请求的字节到字转换的指令是各种形式的punpack。在x64上,我发现的唯一一个是取m256i的高或低m128i,并将其分布在整个m256i上。32位代码可能有32到64位的版本,但我在x64代码中找不到使其工作的方法。@SoronelHaetir,任务是将位传递到指定的位置。这相当于其他解决方案
 __m128i value1 = _mm_setr_epi8(0x11, 0x22, 0x33, 0x44, 
    0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00);
 __m256i value2 = _mm256_cvtepu8_epi16(value1);