5

将两个字节打包成一个的最快方法是什么?我有大量的字节。每个字节代表一个不大于 15 的数字(4 位数字)。因此,我可以将两个字节打包成一个字节,将第一个字节放入高半字节,然后将后半字节放入低半字节。

我目前的方法是创建一个原始数组一半大小的第二个数组,然后迭代原始数组并移动它和 | 得到小食。这可行,但是需要一段时间,具体取决于数组的大小。数组从几千个条目到几百万个。这不是灾难性的,但任何优化都会有所帮助

4

2 回答 2

4

如果您的数组很大,显然需要一段时间 - 您需要遍历所有数组。

我要做的第一件事是创建一个从两个字节到一个字节的查找表,因此您不需要移位和或 - 获取接下来的两个字节,查找它们的偏移量并获得结果字节。

这个查找表应该有 2^12 个条目(你只需要从最高有效字节开始的 4 个字节),并且非常适合你的 CPU 的 L1 缓存。它可能比 shift-and-or 更快。

另一方面,如果您一次加载 8 个字节(在 64 位 CPU 上,就像现在一样),您可以将其转换为 4 个字节并存储它们。您将能够并行化(将数组分成 4 个部分,并让每个核心处理一个部分)。

如果有一条指令从 64 位寄存器中获取字节 0、2、4 和 6 并将它们放入 32 位寄存器中,那么您就完成了。

更新:您在问题中提到您有几百万字节。在这种情况下,不要打扰。高度优化的汇编和 C 中的幼稚实现之间的区别是不值得麻烦的。只需一次加载两个字节的数据,将两个半字节移入一个字节并存储在目标数组中。处理 1MB 的数据应该是即时的。

于 2014-05-02T19:11:09.637 回答
0

我会先在 C 或 C++ 中处理它,测量,然后仅在性能不可接受时才诉诸汇编。在 C 中:

void packarray(unsigned char *buff, int len)
{ 
    unsigned char *packed;
    unsigned char byte;
    assert(len >= 2);  /* len must be at least 2 bytes */
    assert((len & 1) != 1);   /* len must be an even number */
    for (packed = buff; len>0; len-=2) {
        byte= *buff++;
        *packed++ = (byte << 4) | *buff++;
    }
}

警告:未经测试的代码

于 2014-05-02T19:39:11.707 回答