2011-09-08 4 views
8

다른 배열로 복사하는 동안 배열의 바이트 순서 을 효율적으로 바꿔야합니다.복사 중 바이트 스왑

소스 배열은 특정 유형입니다. char, short 또는 int이므로 필요한 바이트 스왑은 명확하고 해당 유형에 따릅니다.

내 계획은 다중 패스 바이트 단위 복사본 (짧게 2 개, int는 4 개 ...)으로 매우 간단하게 수행하는 것입니다. 그러나 기존의 "memcpy_swap_16/32/64"함수 또는 라이브러리가 있습니까? 아마도 BGR/RGB 이미지 처리를위한 이미지 처리에있을 것입니다.

편집이

내가 개별 값의 바이트를 교환하는 방법을 알고, 그것은 문제가되지 않습니다. 어쨌든 수행 할 사본 중에이 과정을 수행하고 싶습니다..

예를 들어, 배열 또는 리틀 엔디안 4 바이트 정수가있는 경우 4의 바이트 수를 사용하여 0, 1, 2 및 3의 초기 오프셋으로 4 바이트 사본을 수행하여 스왑 할 수 있습니다. 더 나은 방법은 아마도 각 4 바이트 정수를 개별적으로 읽고 바이트 스왑 내장 함수 _byteswap_ushort, _byteswap_ulong 및 _byteswap_uint64를 사용하는 것이 더 빠릅니다. 그러나 이러한 유형의 처리를 수행하는 기존 기능이 있어야한다고 생각합니다. 2

편집 그냥 SSE위한 유용한 근거가 될 수있는이를 발견 메모리 대역폭이 아마 시간의 낭비를 만드는 것이 진정한하지만.

Fast vectorized conversion from RGB to BGRA

답변

1

예 데이터의 크기 (이 경우)가 설정 오버 헤드가 너무 높기 때문에 질문에 링크 된 것과 같은 기존 기능이 있지만 노력하지 않아도됩니다. 대신 한 번에 2, 4, 8 바이트를 읽고 내장 함수를 사용하여 스왑을 수행하고 다시 쓰는 것이 좋습니다.

6

유닉스 시스템은 16 비트 배열에 대해 원하는 것을하는 swab 기능을 가지고있다. 아마 최적화되었을 지 모르겠지만. 그냥 순진 바이트 스왑 코드를 작성하는 경우 현대 GCC는 매우 효율적인 코드를 생성합니다 :

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

즉 그것은을 i486 +에 bswap 명령을 사용합니다. 아마도 루프에서이 퍼팅이 너무 효율적인 루프를 ... 줄 것이다

편집 :

  1. 가에서 32 비트 값을 읽기 : 당신의 복사 작업에 대한, 나는 당신의 루프에서 다음을 수행 할 것 const uint32_t *src.
  2. 위 코드를 사용하여 교체하십시오.
  3. uint32_t *dest에 32 비트 값을 씁니다.

엄격히이 휴대용 (앨리어싱 위반) 일 수 있지만 한 복사 기능은 자신의 번역 단위와없는 인라인하기로 걱정하는 거의있을 수 없습니다 말하기. 내가 앨리어싱에 대해 쓴 것을 잊어 버리십시오. 데이터를 32 비트 값으로 바꾼다면 실제로는 실제로 32 비트 값 이었지만 다른 유형의 포인터는 없었으므로 아무런 문제가 없습니다.

+1

컴파일러 바이트 스왑 내장 함수는 올바른 명령어의 사용을 보장하는 더 좋은 방법입니다. 그러나 이것은 문제가 아닙니다. – hplbsh

+0

나는 왜 그걸 "더 나은"것이라고 부를지 모르겠다. 특정 컴파일러에만 한정됩니다. 내가 제공 한 코드는 컴파일러에서 실제로 올바른 작업을하는 "올바른"명령어를 생성합니다. –

+0

최적화되지 않은 디버그 빌드에서도 빠른 속도를 보입니다. – hplbsh

3

리눅스에서는 bits/byteswap.h 헤더를 확인해야합니다. bswap _ ## 형식의 매크로 제품군이 있으며 그 중 일부는 적절한 경우 어셈블리 지침을 사용합니다.

+2

이 헤더는 가증 한 것입니다. 인라인 어셈블리를 사용하여 "빨리"작성한 다음 gcc 확장을 사용하여 인수가 상수 일 때 어셈블리보다 C를 선호하므로 gcc가 상수를 축소 할 수 있습니다. 그리고 그게 그렇게 우스운 일이라면 거의 우스운 것입니다. gcc가 내 답변에 쓴 것처럼 순진한 C를 쓰면 gcc는 그 자체로 똑같은 또는 더 좋은 asm을 생성 할 것입니다. –

+0

@R. 그것은 16,32 , 64 비트 구현을 처리하고 32/64 비트 시스템을 올바로 처리 할 수 ​​있으며'bswap_16 (...) '처럼 간단하게 만듭니다. –

+0

함수가 유용하다는 데 동의합니다. 헤더가 끔찍하게 쓰여졌을뿐입니다. 모든 인라인 asm gcc 확장이 찢어지면 생성 된 코드는 버그 및 비 호환성의 가능성은 거의 사라질 것입니다. 또한, 그것을 정리하면 조기 교육을하지 않는 초보자를 가르치는 데 도움이 될 것입니다 ... –

관련 문제