문제

시간이 중요한 기능에서 상대적으로 짧은 메모리 시퀀스(1KB 미만, 일반적으로 2~200바이트)를 복사하고 싶습니다.CPU 측에서 이에 대한 가장 좋은 코드는 다음과 같습니다. rep movsd.그러나 어떻게든 내 컴파일러가 이 코드를 생성하도록 만들 수 없습니다.memcpy를 사용하면 컴파일러 내장 내장 함수를 사용하여 이 작업을 수행할 수 있기를 바랐지만(어렴풋이 본 기억이 있습니다), 디스어셈블리 및 디버깅을 기반으로 하면 컴파일러가 대신 memcpy/memmove 라이브러리 구현에 대한 호출을 사용하는 것 같습니다.나는 또한 컴파일러가 다음 루프를 인식하고 사용할 수 있을 만큼 똑똑하기를 바랐습니다. rep movsd 그 자체로는 그렇지 않은 것 같습니다.

char *dst;
const char *src;
// ...
for (int r=size; --r>=0; ) *dst++ = *src++;

Visual Studio 컴파일러에서 생성하도록 만드는 방법이 있습니까? rep movsd 인라인 어셈블리를 사용하는 것 이외의 시퀀스는 무엇입니까?

도움이 되었습니까?

해결책 3

일정한 크기로 memcpy 사용

그동안 내가 발견한 것:

복사된 블록 크기가 컴파일 시간에 알려진 경우 컴파일러는 내장 기능을 사용합니다.그렇지 않은 경우 라이브러리 구현을 호출합니다.크기를 알면 생성된 코드는 크기에 따라 선택되어 매우 훌륭합니다.필요에 따라 단일 mov, movsd 또는 movsd 다음에 movsb가 올 수 있습니다.

항상 movsb 또는 movsd를 사용하고 싶다면 "동적" 크기라도 인라인 어셈블리나 특수 내장 함수를 사용해야 할 것 같습니다(아래 참조).나는 크기가 "매우 짧다"는 것을 알고 있지만 컴파일러는 그것을 모르고 이것을 전달할 수 없습니다. 심지어 __assume(size<16)을 사용하려고 시도했지만 충분하지 않습니다.

데모 코드, "-Ob1(인라인 전용 확장)을 사용하여 컴파일:

  #include <memory.h>

  void MemCpyTest(void *tgt, const void *src, size_t size)
  {
    memcpy(tgt,src,size);
  }

  template <int size>
  void MemCpyTestT(void *tgt, const void *src)
  {
    memcpy(tgt,src,size);
  }

  int main ( int argc, char **argv )
  {
    int src;
    int dst;
    MemCpyTest(&dst,&src,sizeof(dst));
    MemCpyTestT<sizeof(dst)>(&dst,&src);
    return 0;
  }

전문 내장 함수

최근에 movsd를 사용하여 Visual Studio 컴파일러에서 문자를 복사하는 매우 자연스럽고 간단한 방법이 있다는 것을 알았습니다.내장 함수를 사용합니다.다음 내장 함수가 유용할 수 있습니다.

다른 팁

몇 가지 질문이 떠 오릅니다.

첫째, MOVSD가 더 빠를 것이라는 것을 어떻게 알 수 있습니까? 대기 시간/처리량을 찾았습니까? X86 아키텍처는 현대 CPU에서는 그다지 효율적이지 않기 때문에 사용해서는 안되는 구식 지침으로 가득합니다.

둘째, 사용하면 어떻게됩니까? std::copy memcpy 대신? std::copy 특정 데이터 유형의 컴파일 타임에 전문화 될 수 있으므로 잠재적으로 더 빠릅니다.

셋째, 프로젝트 속성에서 내재 기능을 활성화 했습니까?> C/C ++ -> 최적화?

물론 다른 최적화도 활성화되어 있다고 가정합니다.

최적화 된 빌드를 실행하고 있습니까? 최적화가 켜져 있지 않으면 고유를 사용하지 않습니다. 또한 Rep Movsd보다 더 나은 사본 루프를 사용할 것임을 주목할 가치가 있습니다. 한 번에 64 비트를 수행하려면 MMX를 사용해야합니다. 실제로 6 년 또는 7 년 전 나는 이런 종류의 일을하기 위해 MMX 최적화 된 사본 루프를 썼습니다. 불행히도 컴파일러의 고유 한 Memcpy는 MMX 사본보다 약 1%성능이 우수했습니다. 그것은 실제로 컴파일러가하는 일에 대해 가정하지 말라고 가르쳐주었습니다.

memcpy를 시간에 적용 했습니까? 최근 버전의 Visual Studio에서 Memcpy 구현은 SSE2를 사용합니다. rep movsd. 복사하는 블록이 1 KB 인 경우, 기능 호출 시간이 사본 시간에 비해 무시할 수 있기 때문에 컴파일러가 고유를 사용하지 않는 것은 실제로 문제가되지 않습니다.

사용하려면 주목하십시오 movsd, src 32 비트 경계에 정렬 된 메모리를 가리켜야하며 길이는 4 바이트의 배수 여야합니다.

그렇다면 코드가 왜 사용됩니까? char * 대신에 int * 또는 뭔가? 그렇지 않다면, 당신의 질문은 무두입니다.

당신이 변하면 char * 에게 int *, 너 ~할 것 같다 더 나은 결과를 얻으십시오 std::copy.

편집하다: 복사가 병목 현상이라고 측정 했습니까?

memcpy를 사용하십시오. 이 문제는 이미 해결되었습니다.

참고로 MOVSD가 항상 최고는 아닙니다. 반복 MOVSB는 어떤 상황에서는 SSE와 같은 MovntQ [Edi], XMM0입니다. 데이터를 버퍼로 이동 한 다음 대상으로 이동하여 페이지 로컬을 사용하여 많은 양의 메모리를 더 최적화 할 수도 있습니다.

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