2011-09-08 47 views
8

我需要在复制到另一个阵列期间有效地交换数组的字节顺序。复制期间的字节交换

源数组是特定类型的; char,short或int,因此所需的字节交换是明确的,并且将根据该类型进行。

我的计划是使用多遍逐字节拷贝(简称为2,简写为int,...)来完成此操作。但是,是否有任何预先存在的“memcpy_swap_16/32/64”函数或库?也许在用于BGR/RGB图像处理的图像处理中。

编辑

我知道如何交换个体值的字节,这是没有问题的。我想在的副本中执行此过程,我将执行

例如,如果我有一个数组或小端的4字节整数,我可以通过执行4个按字节复制,初始偏移量为0,1,2和3,步长为4来进行交换。一种更好的方法,甚至可以单独读取每个4字节的整数,并使用字节交换内部函数_byteswap_ushort,_byteswap_ulong和_byteswap_uint64将会更快。但我怀疑必须有现有的功能来完成这种类型的处理。

EDIT 2

刚刚发现这一点,这可能是上证所的有用基础,但其真正的内存带宽,可能使得它在浪费时间。

Fast vectorized conversion from RGB to BGRA

回答

1

是的,现有的功能就像问题中链接的功能一样,但不值得费力,因为数据的大小(在这种情况下)意味着设置开销太高。相反,最好一次只读出2,4和8个字节,并使用内部函数和回写进行交换。

6

Unix系统有一个swab函数,你想要做什么16位阵列。这可能是优化的,但我不确定。需要注意的是现代的GCC将产生非常高效的代码,如果你只写天真字节交换代码:

uint32_t x, y; 
y = (x<<24) | (x<<8 & 0xff0000) | (x>>8 & 0xff00) | (x>>24); 

即它将使用bswap指令上的i486 +。据推测,这将在一个循环中会给出一个有效的循环太...

编辑:为了您的复印任务,我会做你的循环如下:

  1. 阅读从32位值const uint32_t *src
  2. 使用上面的代码来交换它。
  3. 将32位值写入uint32_t *dest

严格来说,这可能不是便携式(别名冲突),但只要复制功能是在其自己的翻译单元,并没有得到内联,有很少操心。 忘记我写的关于别名的东西;如果您将数据交换为32位值,那么它几乎肯定是以32位值开头的,而不是其他类型的指针,因此没有问题。

+1

编译器字节交换内在函数是保证使用正确指令的更好方法。但这不是问题。 – hplbsh

+0

我不确定你为什么称他们为“更好”。它们特定于特定的编译器。我给出的代码将在任何真正困扰优化的编译器上生成“正确”指令。 –

+0

因为即使在未优化的调试版本中它也会很快。 – hplbsh

3

在linux中,你应该检查标题bits/byteswap.h。有一组bswap _ ##形式的宏,其中一些在适当的地方使用汇编指令。

+2

这个头文件的写法是一种令人憎恶的东西,他们使用内联汇编使其“快速”,然后gcc扩展来支持C上的汇编,因为参数是常量,所以gcc可以折叠常量。但是 - 如果它不那么令人伤心,这就是让它变得有趣的地方 - 如果你只是像我在我的回答中写的那样写出天真的C,gcc就会自己生成相同或更好的asm –

+0

@R。它包含16,32 ,64位实现并正确处理32/64位系统,并使它像'bswap_16(...)'一样简单 –

+0

我同意这些函数是有用的我只是声称头是可怕的写入如果所有的内联asm并且gcc扩展被剥离出来,生成的代码将会一样好或者更好,并且错误和不兼容性的可能性几乎将被消除。此外,清理它将有助于教新手不要练习过早优化... –