c++ - 给定一个整数数组,将数组从中间拆分为两个短数组的最有效方法是什么?

标签 c++ c arrays algorithm

我突然想到一定有一种聪明的方法可以做到这一点。这不是为了家庭作业,或工作或任何东西。我只是在研究一种数据交错的文件格式。

因此,在通用 C/C++ 中,(或其他)给定一些数组

int x[] = ...

有没有巧妙的方法将它分成两个短数组

short sa1[], sa2[]

使得 int 数组从中间 split

x[i] = 1111111111111111 1111111111111111
             sa1[i]         sa2[i]

编辑:抱歉,如果措辞不当。对于 int 数组的每个第 i 个元素,最左边的 16 位成为一个数组的第 i 个元素,最右边的 16 位成为第二个数组的第 i 个元素。

如此给定

x[i] = 0001111111111111 1111111100011111

然后

sa1[i] = 0001111111111111
sa2[i] = 1111111100011111

我正在寻找不在每个元素上循环并移动和屏蔽每个元素的非显而易见的答案。这很容易:)

最佳答案

有很多方法可以做到这一点:

假设:

  1. short 是 16 位。
  2. int 是 32 位。

方法一:(一个简单的循环)

for (int i = 0; i < size; i++){
    int tmp = x[i];
    sa1[i] = (tmp      ) & 0xffff;
    sa2[i] = (tmp >> 16) & 0xffff;
}

方法二:SSE2

for (int i = 0; i < size / 8; i++){
    __m128i a0 = ((__m128i*)x)[2*i + 0];
    __m128i a1 = ((__m128i*)x)[2*i + 1];

    a0 = _mm_shufflelo_epi16(a0,216);
    a1 = _mm_shufflelo_epi16(a1,216);
    a0 = _mm_shufflehi_epi16(a0,216);
    a1 = _mm_shufflehi_epi16(a1,216);
    a0 = _mm_shuffle_epi32(a0,216);
    a1 = _mm_shuffle_epi32(a1,216);

    ((__m128i*)sa1)[i] = _mm_unpacklo_epi64(a0,a1);
    ((__m128i*)sa2)[i] = _mm_unpackhi_epi64(a0,a1);
}

如果进一步展开循环,最后一个例子会非常快。如果这可以击败所有字节操作库,我不会感到惊讶。

但是,它有以下限制:

  1. 数据必须对齐到 16 字节。
  2. 迭代次数必须能被 8 整除。
  3. 它需要 SSE2。

前两个可以通过清理代码解决。这很困惑,但如果您真的想要性能,那可能是值得的。

编辑:

是的,这违反了严格别名,但不这样做几乎不可能使用 SSE 内在函数。

关于c++ - 给定一个整数数组,将数组从中间拆分为两个短数组的最有效方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7550102/

相关文章:

java - 具有增强 for 循环的字符串数组

c++ - C++ 中的多维复数值数组

c++ - 为什么不能构造包含 ostringstream 成员的对象?

c - 不会创建txt文件的C程序

c - NVIC 中断不适用于 STM32F103

计算子进程fork()的进程运行时间

arrays - 在 Perl 中的哈希中遍历哈希数组

c - 我正确加载我的字符数组吗?

c++ - 奇怪的编译问题 - DLL 在某些机器上编译不一样

c++ - C++中删除数组中的元素