2014-02-09 9 views
4

snappy의 내부에는 이러한 작업 (예 : x86)을 지원하는 것으로 알려진 아키텍처에서 잠재적으로 정렬되지 않은 16, 32 및 64 비트 정수를 읽고 쓸 수있는 최상의 구현으로 dereferencing a reinterpret_cast'ed 포인터를 선택하는 조건부로 컴파일 된 섹션이 있습니다. . 다른 아키텍처의 대체 방법은 memcpy based implementation입니다.정렬되지 않은 메모리 액세스 대 memcpy에 대한 reinterpret_cast의 유효한 유스 케이스는 무엇입니까?

제 생각에 reinterpret_cast 구현은 정의되지 않은 동작을 나타내며 clang의 정의되지 않은 동작은 새니 타이 저의 플래그입니다.

내가 당황한 이유는 다음과 같습니다. memcpy 기반 구현을 사용하지 않는 이유는 무엇입니까? 크기가 컴파일 타임에 알려지기 때문에이 memcpy 호출을 구현하는 데 intrinsic을 사용하는 컴파일러 중 가장 많이 망가진 컴파일러를 제외하고는 모두 기대할 것입니다. 사실 모든 현대적인 툴체인에서 구현 된 것과 동일한 코드gen을 기대합니다.

그러나 나는 또한 그들이 뭘 알고 있는지 사람들이 작성한 것으로 알고 있습니다. 그래서 이것은 정의되지 않은 행동을 능가하는 reinterpret_cast 메카니즘을 사용하는 것에 여전히 이점이 있는지 궁금하게 생각합니다. 컴파일러의 구현 품질에 따라 성능을 원하지 않습니까? 내가 고려하지 않은 다른 것?

+1

소리가 지뢰밭과 같습니다. 처음에는 정렬되지 않은 주소의 객체를 얻거나 * 얻는 올바른 방법이 없으므로이 코드의 유일한 사용 사례는 I/O이므로이 코드는 줄 바꿈되어있는 것처럼 보입니다 "정수를 비 직렬화"하는 것. –

+0

@KerrekSB 예, 이것은 IO 또는 프로토콜/형식 크래킹 코드입니다. 그러나 문자 배열 바이트의 정렬에 대한 참조없이 char 배열을 통해 쉽게 복사 가능한 유형 (명시 적 폭의 정수 유형이 확실 함)을 왕복 할 수 있음을 명시하는 3.9.2 절 [기본 유형]을 참조하십시오. 그래서 memcpy 구현은 확실히 정의 된 동작이다. 그리고 reinterpret_cast는 확실히 정의되지 않았습니다. – acm

+0

[이 커밋] (https://code.google.com/p/snappy/source/detail?r=59&path=/trunk/snappy-stubs-internal.h)에 첨부 된 설명이 흥미 롭습니다. 분명히 성능에 차이가 있습니다. –

답변

2

그 코드를 처음 작성한 프로그래머를 알지 못하면 진정한 권위있는 대답을 얻을 수 있을지 의심 스럽습니다.

내 생각에 가장 좋은 추측은 다음과 같습니다. 작성자는 memcpy 개의 최적화 (많은 컴파일러에서 구현 되더라도 사양에 의해 보장되지는 않음)에 의존하기를 원하지 않았습니다. 반면에 reinterpret_cast을 쓰는 것은 사실상 모든 컴파일러에서 저자가 기대했던 정렬되지 않은 액세스 명령어를 생성 할 가능성이 매우 높습니다.

똑똑하고 현대적인 컴파일러는 memcpy을 최적화하지만 이전 버전은 그렇지 않을 수도 있습니다. 일관성있는 성능은이 라이브러리에서 매우 중요 할 수 있습니다. 따라서 광범위한 컴파일러 집합에서보다 일관된 결과를 얻으려는 정확성을 희생 한 것으로 보입니다 (reinterpret_cast이 잠재적으로 UB로 표시되기 때문에).

-1

이유는 정렬되지 않은 주소에서 int를 복사 한 다음로드하는 것보다 빠릅니다 (x86에서).

정렬되지 않은로드의 오버 헤드는 약 2입니다. memcpy는 4 바이트 읽기, 4 바이트 쓰기 (또는 컴파일러에 따라 하나의 32 비트 쓰기)로 내려 가고,로드가 여전히 필요합니다. 최상의 경우 최적화 프로그램은 write-after-read가 중복되는 것을 발견 할 수 있습니다.

개인적으로, 나는 안전한 방법을 교대로 4 바이트로드로 구현할 것입니다.

+1

많은 경우에 내가 조사한 바에 따르면 두 전략은 x86_64를 대상으로하는 Linux에서 GCC 4.8.1을 사용하여 x86에 대해 동일한 코드를 생성합니다. – acm

+1

실제로 memcpy 전략을 사용하면 reinterpret_cast 방식을 사용하면 memcpy를 사용하지 않고 -fno-strict-aliasing을 사용해야하므로보다 나은 코드를 생성 할 수 있습니다. – acm