문제

C ++에서 memcpy ()에 대한 더 빠른 대안이 있습니까?

도움이 되었습니까?

해결책

할 것 같지 않은. 컴파일러/표준 라이브러리는 Memcpy의 매우 효율적이고 맞춤형 구현을 가질 것입니다. 그리고 Memcpy는 기본적으로 메모리의 한 부분을 다른 부분에 복사하기위한 가장 낮은 API입니다.

추가 스피드 업을 원한다면 메모리 복사가 필요하지 않는 방법을 찾으십시오.

다른 팁

첫째, 조언의 말. 표준 도서관을 쓴 사람들이 어리석지 않다고 가정하십시오. 일반적인 memcpy를 구현하는 더 빠른 방법이 있다면, 그들은 그것을했을 것입니다.

둘째, 그렇습니다. 더 나은 대안이 있습니다.

  • C ++에서 사용하십시오 std::copy 기능. 그것은 똑같은 일을하지만 1) 더 안전하고 2) 경우에 따라 더 빠릅니다. 템플릿으로, 특정 유형에 대해 전문화 될 수 있음을 의미하여 일반 C Memcpy보다 잠재적으로 더 빠릅니다.
  • 또는 우수한 지식을 사용할 수 있습니다 당신의 특정 상황. Memcpy의 구현자는 그것을 써야했기 때문에 잘 수행했습니다. 모든 사례. 필요한 상황에 대한 특정 정보가있는 경우 더 빠른 버전을 작성할 수 있습니다. 예를 들어, 얼마나 많은 메모리를 복사해야합니까? 어떻게 정렬됩니까? 더 효율적인 memcpy를 쓸 수 있습니다. 이것 특정 사례. 그러나 대부분의 다른 경우에는 좋지 않을 것입니다 (전혀 작동하지 않는다면)

최적화 전문가 Agner Fog는 최적화 된 메모리 기능을 발표했습니다. http://agner.org/optimize/#asmlib. 그래도 GPL 아래에 있습니다.

얼마 전 Agner는 이러한 기능이 GCC 빌드 딘을 훨씬 더 빠르기 때문에 대체해야한다고 말했다. 그 이후로 끝났는지 모르겠습니다.

이 답변은 매우 유사한 질문에 대한 답변입니다 memset())도 여기에 적용됩니다.

기본적으로 컴파일러는 매우 최적의 코드를 생성한다고 말합니다. memcpy()/memset() - 객체의 특성 (크기, 정렬 등)에 따라 다른 코드.

그리고 만 기억하십시오 memcpy() C ++의 포드.

빠른 메모리 사본 루틴을 찾거나 작성하려면 프로세서의 작동 방식을 이해해야합니다.

Intel Pentium Pro 이후 프로세서는“외부 실행”을 수행합니다. 지침에 종속성이없는 경우 많은 지침을 병렬로 실행할 수 있습니다. 그러나 이것은 지침이 레지스터로만 작동하는 경우에만 해당됩니다. 메모리와 함께 작동하는 경우 "로드 장치"(메모리에서 데이터를 읽기 위해) 및 "저장 장치"(메모리에 데이터를 작성하기 위해)라고하는 추가 CPU 장치가 사용됩니다. 대부분의 CPU에는 두 개의로드 장치와 1 개의 매장 단위가 있습니다. 즉, 메모리에서 읽는 두 개의 지침과 메모리에 기록하는 하나의 명령어 (다시 서로 영향을 미치지 않으면)를 병렬로 실행할 수 있습니다. 이 단위의 크기는 일반적으로 최대 레지스터 크기와 동일합니다. CPU에 XMM 레지스터 (SSE)가있는 경우 16 바이트, YMM 레지스터 (AVX)가있는 경우 16 바이트입니다. 32 바이트 등입니다. 메모리를 읽거나 쓰는 모든 지침은 Micro-OPS (Micro-OPS)로 번역되어 공통 마이크로 -OPS 풀로 이동하여로드 및 저장 장치가 제공 할 수있을 때까지 기다립니다. 단일로드 또는 저장 장치는로드하거나 저장하는 데 필요한 데이터 크기에 관계없이 1 바이트 또는 32 바이트라면 한 번에 하나의 마이크로 -OP를 제공 할 수 있습니다.

따라서 가장 빠른 메모리 사본은 최대 크기의 레지스터를 오가는 것입니다. AVX 지원 프로세서의 경우 메모리를 복사하는 가장 빠른 방법은 다음 순서를 반복하는 것입니다.

vmovdqa     ymm0,ymmword ptr [rcx]
vmovdqa     ymm1,ymmword ptr [rcx+20h]
vmovdqa     ymmword ptr [rdx],ymm0
vmovdqa     ymmword ptr [rdx+20h],ymm1

HPLBSH가 이전에 게시 한 Google 코드는 8 XMM 레지스터를 모두 사용하여 데이터를 작성하기 전에 데이터를 보유하기 때문에 필요하지는 않지만 두 개의로드 장치와 1 개의 매장 단위 만 가지고 있기 때문에 데이터를 다시 작성하기 전에 데이터를 보유하고 있기 때문입니다. 따라서 두 개의 레지스터 만 최상의 결과를 제공합니다. 이 많은 레지스터를 사용하면 성능이 향상되지 않습니다.

메모리 사본 루틴은 또한 "Prefetch"와 같은 "고급"기술을 사용하여 프로세서에 미리 캐시에 메모리를로드하도록 지시하고 "비 일시적인 쓰기"(매우 큰 메모리 청크를 복사하고 데이터가 필요하지 않은 경우 데이터가 필요하지 않은 경우. 출력 버퍼에서 즉시 읽을 수 있습니다), 정렬 된 대 정렬되지 않은 쓰기 등.

2013 년부터 출시 된 최신 프로세서는 CPUID에 ERM 비트가있는 경우 "Enhanced Rep MOVSB"를 소위로 사용하므로 큰 메모리 사본의 경우 "REP MOVSB"가 사용될 수 있습니다. 사본도 매우 빠르게 사용될 수 있습니다. YMM 레지스터보다 빠르며 캐시로 제대로 작동합니다. 그러나이 명령어의 시작 비용은 매우 높기 때문에 약 35주기이므로 큰 메모리 블록에서만 지불합니다.

이제 귀하의 경우 필요한 최고의 메모리 사본 루틴을 선택하거나 작성하는 것이 더 쉬워지기를 바랍니다.

표준 memcpy/memmove를 유지할 수도 있지만 귀하의 요구에 대해 자신만의 특별한 대단사를 얻을 수 있습니다.

당신이하려는 일에 따라 ... 충분히 큰 memcpy이고, 당신이 사본에 드물게 글을 쓰고 있다면, mmap_private가있는 MMAP는 사본-쓰기 매핑을 만들 수 있습니다.

플랫폼에 따라 소스와 대상이 캐시 라인에 정렬되고 크기가 캐시 라인 크기의 정수 배수 인 경우와 같이 특정 사용 사례가있을 수 있습니다. 일반적으로 대부분의 컴파일러는 Memcpy에 대해 상당히 최적의 코드를 생성합니다.

기본 memcpy를 사용하는 것이 항상 최선의 선택인지 잘 모르겠습니다. 내가 본 대부분의 memcpy 구현은 처음에 데이터를 정렬하고 정렬 한 다음 사본을 정렬하는 경향이 있습니다. 데이터가 이미 정렬되었거나 아주 작 으면 시간이 낭비됩니다.

때로는 캐시에 너무 부정적인 영향을 미치지 않는 한 특수 단어 사본, 반 단어 사본, 바이트 카피 Memcpy를 갖는 것이 좋습니다.

또한 실제 할당 알고리즘을 더 잘 제어 할 수 있습니다. 게임 업계에서는 사람들이 툴체인 개발자가 처음으로 개발 한 시간에 관계없이 자신의 메모리 할당 루틴을 작성하는 것이 매우 일반적입니다. 내가 본 게임은 거의 항상 사용하는 경향이 있습니다 Doug Lea의 Malloc.

그러나 일반적으로 말하면, 당신은 응용 프로그램에서 속도를 높이기 위해 더 쉬운 코드의 더 쉬운 코드가 많을 것이기 때문에 Memcpy를 최적화하려는 시간을 낭비하고 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top