성능 측면에서 std :: memcpy () 또는 std :: copy ()를 사용하는 것이 더 낫습니까?


163

memcpy아래 그림과 같이 사용 하는 것이 좋 std::copy()습니까? 아니면 성능 측면에서 사용하는 것이 더 낫 습니까? 왜?

char *bits = NULL;
...

bits = new (std::nothrow) char[((int *) copyMe->bits)[0]];
if (bits == NULL)
{
    cout << "ERROR Not enough memory.\n";
    exit(1);
}

memcpy (bits, copyMe->bits, ((int *) copyMe->bits)[0]);

참고 char구현에 따라, 서명 또는 부호 될 수있다. 바이트 수가> = 128 일 수있는 경우 unsigned char바이트 배열에 사용 하십시오. ( (int *)캐스트도 더 안전 할 것 (unsigned int *)입니다.)
Dan Breslau

13
왜 사용하지 std::vector<char>않습니까? 아니면 당신이 말하기 bits때문에 std::bitset?
GManNickG

2
실제로, 무엇을 설명해 주 (int*) copyMe->bits[0]시겠습니까?
user3728501

4
왜 그렇게 중요한 맥락을 제공하지 않는 그런 엉망인 것처럼 보이는 것이 확실하지 않은지 +81입니다. @ user3728501 제 생각에는 버퍼의 시작 부분에 int크기가 결정되어 있지만 여기에는 다른 많은 것들과 같이 구현 정의 재해의 레시피처럼 보입니다.
underscore_d

2
실제로, (int *)캐스트는 구현 정의가 아닌 순수한 정의되지 않은 동작입니다. 캐스트를 통해 타이핑을하려고하면 엄격한 앨리어싱 규칙을 위반하므로 표준에 따라 완전히 정의되지 않습니다. (또한, C 아니지만 C ++로, 당신은 비아 말장난을 입력 할 수 없습니다 union중 하나.) 당신이 변환하는 경우 거의 유일한 예외는 의 변형 char*만 허용 대칭이 아니다.
underscore_d

답변:


207

나는 std::copy약간의 거의 눈에 띄지 않는 성능 손실 을 가져올 일반적인 지혜에 반대 할 것입니다. 방금 테스트를 수행하여 사실이 아님을 발견했습니다. 성능 차이를 발견했습니다. 그러나 우승자는 std::copy입니다.

C ++ SHA-2 구현을 작성했습니다. 내 테스트에서 4 개의 SHA-2 버전 (224, 256, 384, 512)을 모두 사용하여 5 개의 문자열을 해시하고 300 번 반복합니다. Boost.timer를 사용하여 시간을 측정합니다. 그 300 루프 카운터는 내 결과를 완전히 안정화시키기에 충분합니다. memcpy버전과 버전을 번갈아 가며 테스트를 각각 5 회 실행했습니다 std::copy. 내 코드는 가능한 한 많은 청크에서 데이터를 가져 오는 이점을 활용합니다 (다른 구현은 char/로 char *작동하지만 T/는 T *( T오버 플로우 동작이 올바른 사용자 구현에서 가장 큰 유형 임) 작동하므로 빠른 메모리 액세스 내가 할 수있는 가장 큰 유형은 알고리즘 성능의 핵심입니다.

SHA-2 테스트 실행을 완료하는 데 걸리는 시간 (초)

std::copy   memcpy  % increase
6.11        6.29    2.86%
6.09        6.28    3.03%
6.10        6.29    3.02%
6.08        6.27    3.03%
6.08        6.27    3.03%

memcpy보다 std :: copy의 총 평균 속도 증가 : 2.99 %

내 컴파일러는 Fedora 16 x86_64에서 gcc 4.6.3입니다. 내 최적화 플래그는 -Ofast -march=native -funsafe-loop-optimizations입니다.

내 SHA-2 구현을위한 코드입니다.

MD5 구현에서도 테스트를 실행하기로 결정했습니다. 결과는 훨씬 덜 안정적이어서 10 번의 런을하기로 결정했습니다. 그러나 처음 몇 번의 시도 후에는 실행마다 크게 다른 결과가 나타 났으므로 일종의 OS 활동이 진행되고 있다고 생각합니다. 나는 다시 시작하기로 결정했다.

동일한 컴파일러 설정 및 플래그. MD5에는 한 가지 버전 만 있으며 SHA-2보다 빠르므로 비슷한 5 개의 테스트 문자열 세트에서 3000 회 반복했습니다.

이것들은 나의 최종 10 결과입니다 :

MD5 테스트 실행을 완료하는 데 걸리는 시간 (초)

std::copy   memcpy      % difference
5.52        5.56        +0.72%
5.56        5.55        -0.18%
5.57        5.53        -0.72%
5.57        5.52        -0.91%
5.56        5.57        +0.18%
5.56        5.57        +0.18%
5.56        5.53        -0.54%
5.53        5.57        +0.72%
5.59        5.57        -0.36%
5.57        5.56        -0.18%

memcpy에 비해 std :: copy의 총 평균 속도 감소 : 0.11 %

내 MD5 구현을위한 코드

이 결과는 std::copyMD5 테스트에 사용할 수없는 SHA-2 테스트에 std :: copy가 최적화되어 있음을 나타 냅니다. SHA-2 테스트에서 두 배열은 모두 std::copy/ 와 같은 함수로 작성되었습니다 memcpy. 내 MD5 테스트에서 배열 중 하나가 함수에 함수 매개 변수로 전달되었습니다.

나는 std::copy더 빨리 만들기 위해 무엇을 할 수 있는지 확인하기 위해 조금 더 많은 테스트를 수행 했습니다. 대답은 간단합니다. 링크 시간 최적화를 켜십시오. 다음은 LTO가 켜져있는 결과입니다 (gcc의 옵션 -flto).

-flto를 사용하여 MD5 테스트 실행을 완료하는 데 걸리는 시간 (초)

std::copy   memcpy      % difference
5.54        5.57        +0.54%
5.50        5.53        +0.54%
5.54        5.58        +0.72%
5.50        5.57        +1.26%
5.54        5.58        +0.72%
5.54        5.57        +0.54%
5.54        5.56        +0.36%
5.54        5.58        +0.72%
5.51        5.58        +1.25%
5.54        5.57        +0.54%

memcpy보다 std :: copy의 총 평균 속도 증가 : 0.72 %

요약하면을 (를) 사용하면 성능이 저하되지 않습니다 std::copy. 실제로 성능이 향상되는 것으로 보입니다.

결과 설명

그렇다면 왜 std::copy성능이 향상 될 수 있습니까?

첫째, 인라인 최적화가 켜져있는 한 구현에 대해 속도가 느려질 것으로 기대하지 않습니다. 모든 컴파일러는 적극적으로 인라인합니다. 그것은 다른 많은 최적화를 가능하게하기 때문에 아마도 가장 중요한 최적화 일 것입니다. std::copy(그리고 모든 실제 구현이 그렇게 생각합니다) 인수가 사소하게 복사 가능하고 메모리가 순차적으로 배치되어 있음을 감지 할 수 있습니다. 이는 최악의 경우 memcpy합법적 인 경우 std::copy더 나쁘게 수행되지 않아야 함을 의미합니다 . 의 사소한 구현 std::copy이 연기를하는 memcpy"항상 인라인이 속도 나 크기로 최적화 할 때"의 컴파일러의 기준을 충족해야한다.

그러나 std::copy더 많은 정보를 유지합니다. 를 호출 std::copy하면 함수는 유형을 그대로 유지합니다. memcpy에서 작동하며 void *거의 모든 유용한 정보가 삭제됩니다. 예를 들어,의 배열을 전달 std::uint64_t하면 컴파일러 또는 라이브러리 구현자가와 64 비트 정렬을 활용할 수 std::copy있지만로 수행하는 것이 더 어려울 수 있습니다 memcpy. 이와 같은 알고리즘의 많은 구현은 먼저 범위의 시작 부분에서 정렬되지 않은 부분에 대해 작업 한 다음 정렬 된 부분, 끝에서 정렬되지 않은 부분을 처리하여 작동합니다. 그것이 모두 정렬되도록 보장되면 코드가 더 간단하고 빨라지며 프로세서의 분기 예측기가 정확 해집니다.

조기 최적화?

std::copy흥미로운 위치에 있습니다. memcpy현대의 최적화 컴파일러 보다 느리거나 때로는 빠를 것으로 기대합니다 . 또한, 당신이 할 수있는 모든 것이 memcpy가능 std::copy합니다. memcpy버퍼에서 오버랩을 허용하지 않는 반면 std::copy한 방향으로 오버랩을 지원합니다 ( std::copy_backward다른 방향으로 오버랩). memcpy단지이 포인터에서 작동 std::copy어떤 반복자에서 작동 ( std::map, std::vector, std::deque, 또는 내 자신의 사용자 정의 유형). 다시 말해, std::copy데이터 덩어리를 복사해야 할 때만 사용해야합니다.


35
이것이 이것이 std::copy2.99 % 또는 0.72 % 또는 -0.11 % 더 빠르다는 것을 의미하지는 않는다는 것을 강조하고 싶습니다 memcpy.이 시간은 전체 프로그램이 실행되는 시간입니다. 그러나 일반적으로 실제 코드의 벤치 마크가 가짜 코드의 벤치 마크보다 유용하다고 생각합니다. 내 전체 프로그램에서 실행 속도가 변경되었습니다. 두 가지 복사 체계의 실제 효과는 여기에 표시된 것보다 더 큰 차이가 있지만 실제 코드에서는 상당한 차이가있을 수 있습니다.
David Stone

2
결과에 동의하지 않지만 결과는 다음과 같습니다. 그러나 한 가지 질문은 (오래 전에 알고 있었고 연구를 기억하지 못하므로 생각하는 방식으로 의견을 말하십시오) 어셈블리 코드를 보지 않았을 것입니다.
ST3

2
제 생각 memcpystd::copy너무 코드의 하나 개의 중요한 조각으로 코드와 실제 메모리 복사 코드를 둘러싼를 최적화 컴파일러 어떤 경우에는 다른 구현을 가지고 있습니다. 그것은 다른 말은 때때로 사람은 너무 후, 다음 다른 심지어 즉, 모든 상황에서 새로운 연구를해야하기 때문에 용도, 조기 또는 바보 최적화되는 결정에서, 무엇을, 더 및 프로그램은 일반적으로 개발되고있다 낫다 일부 사소한 변경은 다른 것보다 기능의 이점이 손실 될 수 있습니다.
ST3

3
@ ST3 : 최악의 경우 합법적 인 경우 std::copy호출하는 사소한 인라인 함수라고 생각합니다 memcpy. 기본 인라인은 부정적인 성능 차이를 제거합니다. 왜 std :: copy가 더 빠를 수 있는지에 대한 약간의 설명으로 게시물을 업데이트 할 것입니다.
David Stone

7
매우 유익한 분석. re memcpy : 0.11 % 이상의 std :: copy 속도의 총 평균 감소 수는 정확하지만 결과는 통계적으로 유의하지 않습니다. 평균 차이에 대한 95 % 신뢰 구간은 (-0.013s, 0.025)이며 0을 포함합니다. 다른 소스와 데이터에 차이가 있음을 지적했을 때 성능이 동일하다고 말할 수 있습니다. 참고로, 다른 두 가지 결과는 통계적으로 유의합니다. 우연히이 극한의 시간 차이가 발생할 확률은 약 1 억 (첫 번째)과 20,000 (1) 중 1입니다.
TooTone

78

내가 아는 모든 컴파일러는 간단한 경우를 std::copy로 대체하고 memcpy더 나은 경우 복사본을 벡터화하여 a보다 빠릅니다 memcpy.

어쨌든 : 프로필을 작성하고 자신을 찾으십시오. 다른 컴파일러는 다른 작업을 수행하므로 요청한 내용을 정확하게 수행하지 못할 수도 있습니다.

컴파일러 최적화에 대한이 프레젠테이션을 참조하십시오 (pdf).

간단한 POD 유형에 대해 GCC가 수행 하는 작업은 다음과 같습니다 std::copy.

#include <algorithm>

struct foo
{
  int x, y;    
};

void bar(foo* a, foo* b, size_t n)
{
  std::copy(a, a + n, b);
}

다음 -O은 호출을 보여주는 분해 ( 최적화 만 )입니다 memmove.

bar(foo*, foo*, unsigned long):
    salq    $3, %rdx
    sarq    $3, %rdx
    testq   %rdx, %rdx
    je  .L5
    subq    $8, %rsp
    movq    %rsi, %rax
    salq    $3, %rdx
    movq    %rdi, %rsi
    movq    %rax, %rdi
    call    memmove
    addq    $8, %rsp
.L5:
    rep
    ret

함수 서명을로 변경하면

void bar(foo* __restrict a, foo* __restrict b, size_t n)

다음은 memmoveA는되고 memcpy약간의 성능 향상을 위해. 주의 memcpy자체가 크게 벡터화됩니다.


1
프로파일 링을 어떻게 수행 할 수 있습니까? 어떤 도구를 사용해야합니까 (Windows 및 Linux에서)?
user576670

5
@ Konrad, 당신은 맞습니다. 그러나 memmove더 빨라서는 안됩니다. 오히려 두 데이터 범위가 겹칠 가능성을 고려해야하기 때문에 조금 느려 야합니다. 내 생각 std::copy허가 데이터를 중복하고 전화를 가지도록 memmove.
Charles Salvia

2
@ Konrad : memmove가 항상 memcpy보다 빠르면 memcpy는 memmove를 호출합니다. std :: copy가 실제로 전달할 수있는 것은 구현 정의되어 있으므로 구현을 언급하지 않고 세부 사항을 언급하는 것은 유용하지 않습니다.
Fred Nurk

1
이 동작을 재현하는 간단한 프로그램이지만 GCC에서 -O3으로 컴파일하면 a가 표시 memcpy됩니다. GCC가 메모리 오버랩이 있는지 확인한다고 믿습니다.
jweyrich

1
@ Konrad : 표준 std::copy은 한 방향으로 겹치지 만 다른 방향으로는 겹치지 않습니다. 출력의 시작은 입력 범위 내에있을 수 없지만 입력의 시작은 출력 범위 내에 놓일 수 있습니다. 할당 순서가 정의되어 있고 해당 할당의 효과가 순서대로 정의되어 있어도 호출이 UB 일 수 있기 때문에 이것은 조금 이상합니다. 그러나 제한이 벡터화 최적화를 허용한다고 가정합니다.
Steve Jessop

24

항상 사용 std::copy하기 때문에 memcpy단지 C 스타일의 POD 구조로 제한되고, 컴파일러는 가능성에 전화를 대체 할 std::copymemcpy목표는 사실 POD에있는 경우.

또한 std::copy포인터뿐만 아니라 많은 반복기 유형과 함께 사용할 수 있습니다. std::copy성능 손실없이 더 유연하고 확실한 승자입니다.


왜 이터레이터를 복사해야합니까?
Atmocreations

3
반복자를 복사하는 것이 아니라 두 반복자가 정의한 범위를 복사하는 것입니다. 예를 들어, 및의 사이에있는 모든 std::copy(container.begin(), container.end(), destination);내용을 로 표시된 버퍼에 복사합니다 . 나 같은 shenanigans가 필요하지 않습니다 . containerbeginenddestinationstd::copy&*container.begin()&container.back() + 1
David Stone

16

이론적으로, memcpy있을 수 있습니다 약간의 , 눈에 보이지 않는 , 미소 가 같은 요구 사항이없는 경우에만 있기 때문에, 성능상의 이점을 std::copy. 의 맨 페이지에서 memcpy:

오버플로를 피하기 위해, 대상 및 소스 매개 변수가 가리키는 어레이의 크기는 최소 num 바이트 여야하며 겹치지 않아야합니다 (메모리 블록이 겹치는 경우 memmove가 더 안전한 방법입니다).

즉, memcpy데이터가 겹칠 가능성을 무시할 수 있습니다. (겹치는 배열을 전달하는 memcpy것은 정의되지 않은 동작입니다.) 따라서이 memcpy조건을 명시 적으로 확인할 필요 는 없지만 매개 변수가 소스 범위에 있지 않는 한 std::copy사용할 수 있습니다 OutputIterator. 이 참고 하지 원본 범위와 대상 범위가 중복 수 없다는 같은.

따라서 std::copy약간 다른 요구 사항이 있기 때문에 이론 상으로는 C 배열이 겹치는 지 확인하거나 C- 어레이 복사를 위임 해야하기 때문에 약간 (심하게 약간 강조 ) 느려 야 memmove합니다. 검사. 그러나 실제로는 (그리고 대부분의 프로파일 러) 아마 차이를 감지하지 못할 것입니다.

당신이 작동하지 않는 경우 물론, 포드 , 당신은 할 수 사용 memcpy어쨌든.


7
이것은 사실입니다 std::copy<char>. 그러나 std::copy<int>입력이 정렬되어 있다고 가정 할 수 있습니다. 그것은 모든 요소에 영향을 미치기 때문에 훨씬 더 큰 차이를 만들 것입니다. 오버랩은 일회성 검사입니다.
MSalters

2
@MSalters, true, 그러나 대부분의 구현은 memcpy정렬을 확인하고 바이트 단위가 아닌 단어를 복사하려고 시도합니다.
Charles Salvia

1
std :: copy ()는 중복 메모리도 무시할 수 있습니다. 겹치는 메모리를 지원하려면 적절한 상황에서 std :: reverse_copy ()를 호출하는 논리를 직접 작성해야합니다.
Cygon

2
반대 의견이있을 수 있습니다. memcpy인터페이스를 통과 할 때 정렬 정보가 손실됩니다. 따라서 memcpy정렬되지 않은 시작과 끝을 처리하려면 런타임에 정렬 검사를 수행해야합니다. 그러한 수표는 저렴하지만 무료는 아닙니다. 반면 std::copy이러한 확인을 피하고 벡터화 할 수 있습니다. 또한, 컴파일러는 소스 및 대상 배열 사이에서 선택을 갖는 사용자가없는 것은 중복 다시 벡터화 할 것을 증명할 수 memcpymemmove.
Maxim Egorushkin 2016 년

11

내 규칙은 간단합니다. C ++를 사용하는 경우 C가 아닌 C ++ 라이브러리를 선호하십시오. :)


40
C ++는 C 라이브러리를 사용할 수 있도록 명시 적으로 설계되었습니다. 이것은 사고가 아니었다. C ++에서는 memcpy보다 std :: copy를 사용하는 것이 더 좋지만 C와 관련이 없으며 일반적으로 잘못된 인수입니다.
Fred Nurk

2
@FredNurk 일반적으로 C ++가 더 안전한 대안을 제공하는 약한 C 영역을 피하려고합니다.
Phil1970

@ Phil1970이 경우 C ++이 훨씬 안전하다는 것을 확신하지 못합니다. 우리는 여전히 등 I 오버런하지 않는 유효한 반복자 통과해야 추측 사용할 수있는 std::end(c_arr)대신에 c_arr + i_hope_this_is_the_right_number_of elements안전을? 그리고 아마도 더 중요하고 명확합니다. 그리고 이것이 특정한 경우에 강조하는 요점 std::copy()입니다. 반복자의 유형이 나중에 변경되고 구문이 더 명확 해지면 더 관용적이며 유지 보수가 용이합니다.
underscore_d

1
@underscore_d std::copy는 POD 유형이 아닌 경우 전달 된 데이터를 올바르게 복사하므로 더 안전합니다. memcpy행복하게 std::string객체를 새로운 표현으로 바이트 단위로 복사합니다 .
Jens

3

그냥 약간의 추가 : 사이의 속도 차이 memcpy()std::copy()최적화가 활성화 또는 비활성화 경우에 따라 상당히 다를 수 있습니다. g ++ 6.2.0 및 최적화가 없으면 memcpy()분명히 승리합니다.

Benchmark             Time           CPU Iterations
---------------------------------------------------
bm_memcpy            17 ns         17 ns   40867738
bm_stdcopy           62 ns         62 ns   11176219
bm_stdcopy_n         72 ns         72 ns    9481749

최적화가 활성화되면 ( -O3) 모든 것이 거의 동일하게 보입니다.

Benchmark             Time           CPU Iterations
---------------------------------------------------
bm_memcpy             3 ns          3 ns  274527617
bm_stdcopy            3 ns          3 ns  272663990
bm_stdcopy_n          3 ns          3 ns  274732792

배열이 클수록 효과가 눈에 띄지 않지만 N=1000 memcpy()최적화가 활성화되지 않은 경우 에도 2 배 빠릅니다.

소스 코드 (Google 벤치 마크 필요) :

#include <string.h>
#include <algorithm>
#include <vector>
#include <benchmark/benchmark.h>

constexpr int N = 10;

void bm_memcpy(benchmark::State& state)
{
  std::vector<int> a(N);
  std::vector<int> r(N);

  while (state.KeepRunning())
  {
    memcpy(r.data(), a.data(), N * sizeof(int));
  }
}

void bm_stdcopy(benchmark::State& state)
{
  std::vector<int> a(N);
  std::vector<int> r(N);

  while (state.KeepRunning())
  {
    std::copy(a.begin(), a.end(), r.begin());
  }
}

void bm_stdcopy_n(benchmark::State& state)
{
  std::vector<int> a(N);
  std::vector<int> r(N);

  while (state.KeepRunning())
  {
    std::copy_n(a.begin(), N, r.begin());
  }
}

BENCHMARK(bm_memcpy);
BENCHMARK(bm_stdcopy);
BENCHMARK(bm_stdcopy_n);

BENCHMARK_MAIN()

/* EOF */

18
최적화가 비활성화 된 상태에서 성능을 측정하는 것은 ... 글쎄 ... 거의 무의미합니다 ... 성능에 관심이 있다면 최적화 없이는 컴파일하지 않을 것입니다.
bolov

3
@bolov 항상 그런 것은 아닙니다. 디버그 중에 비교적 빠른 프로그램이 필요한 경우가 있습니다.
Acorn

2

실제로 최대 복사 성능이 필요한 경우 (아마도) 사용하지 마십시오 .

메모리 복사를 최적화하기 위해 수행 할 수있는 작업 이 많이 있습니다. 여러 스레드 / 코어를 사용하려는 경우 훨씬 더 좋습니다. 예를 들어 :

이 memcpy 구현에서 빠졌거나 차선책은 무엇입니까?

질문과 답변 중 일부는 구현을 제안하거나 구현에 대한 링크를 제안했습니다.


4
pedant 모드 : 일반적인 경고에서 " 둘 중 어느 것도 사용하지 않음 "은 구현에서 제공하는 표준 기능이 충분히 빠르지 않은 특정 상황 / 요구 사항이 있음을 입증 한 경우를 의미 합니다 . 그렇지 않으면, 나의 일반적인 관심사는 프로그램의 일반적으로 더 유용한 부분 대신 복사 코드를 조기에 최적화하는 것에 대해 부적절하게 입증 된 사람들입니다.
underscore_d

-2

프로파일 링은 다음과 같은 진술을 보여줍니다. std::copy()항상 빠르 memcpy()거나 빠르다는 것은 거짓입니다.

내 시스템 :

HP-Compaq-dx7500-Microtower 3.13.0-24- 일반 # 47- 우분투 SMP 5 월 2 일 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU / Linux.

gcc (우분투 4.8.2-19 우분투 1) 4.8.2

코드 (언어 : c ++) :

    const uint32_t arr_size = (1080 * 720 * 3); //HD image in rgb24
    const uint32_t iterations = 100000;
    uint8_t arr1[arr_size];
    uint8_t arr2[arr_size];
    std::vector<uint8_t> v;

    main(){
        {
            DPROFILE;
            memcpy(arr1, arr2, sizeof(arr1));
            printf("memcpy()\n");
        }

        v.reserve(sizeof(arr1));
        {
            DPROFILE;
            std::copy(arr1, arr1 + sizeof(arr1), v.begin());
            printf("std::copy()\n");
        }

        {
            time_t t = time(NULL);
            for(uint32_t i = 0; i < iterations; ++i)
                memcpy(arr1, arr2, sizeof(arr1));
            printf("memcpy()    elapsed %d s\n", time(NULL) - t);
        }

        {
            time_t t = time(NULL);
            for(uint32_t i = 0; i < iterations; ++i)
                std::copy(arr1, arr1 + sizeof(arr1), v.begin());
            printf("std::copy() elapsed %d s\n", time(NULL) - t);
        }
    }

g ++ -O0 -o test_stdcopy test_stdcopy.cpp

memcpy () 프로필 : 주 : 21 : 지금 : 1422969084 : 04859 경과 : 2650 us
std :: copy () 프로필 : main : 27 : now : 1422969084 : 04862 경과 : 2745 us
memcpy () 경과 44 s std :: copy ( ) 경과 45 초

g ++ -O3 -o test_stdcopy test_stdcopy.cpp

memcpy () 프로필 : 주 : 21 : 지금 : 1422969601 : 04939 경과 : 2385 us
std :: copy () 프로필 : 주 : 28 : now : 1422969601 : 04941 경과 : 2690 us
memcpy () 경과 27 s std :: copy ( ) 경과 43 초

Red Alert는 코드가 배열에서 배열로 memcpy를 사용하고 배열에서 벡터로 std :: copy를 사용한다고 지적했습니다. 그 말은 더 빠른 memcpy의 이유입니다.

있기 때문에

v.reserve (sizeof (arr1));

벡터 또는 배열에 복사하는 데 차이가 없어야합니다.

코드는 두 경우 모두 배열을 사용하도록 수정되었습니다. memcpy는 여전히 더 빠릅니다.

{
    time_t t = time(NULL);
    for(uint32_t i = 0; i < iterations; ++i)
        memcpy(arr1, arr2, sizeof(arr1));
    printf("memcpy()    elapsed %ld s\n", time(NULL) - t);
}

{
    time_t t = time(NULL);
    for(uint32_t i = 0; i < iterations; ++i)
        std::copy(arr1, arr1 + sizeof(arr1), arr2);
    printf("std::copy() elapsed %ld s\n", time(NULL) - t);
}

memcpy()    elapsed 44 s
std::copy() elapsed 48 s 

1
프로파일 링에 따르면 배열로 복사하는 것이 벡터로 복사하는 것보다 빠릅니다. 주제를 벗어.
Red Alert

내가 잘못했을 수도 있지만 memcpy를 사용하여 수정 한 예제에서 arr2를 arr1에 복사하지 않고 std :: copy를 사용하면 arr1을 arr2에 복사합니까? 실험 (한 번의 memcpy, 한 번의 std :: copy 한 번, memcopy 등으로 여러 번 다시 한 번). 그런 다음 time () 대신 clock ()을 사용합니다. 누가 그 프로그램 외에 PC가 무엇을 할 수 있는지 알고 있기 때문입니다. 그래도 내 두 센트 ... :-)
paercebal

7
따라서 std::copy벡터에서 배열로 전환 하는 memcpy데 어떻게 든 시간이 거의 두 배가 걸립니까? 이 데이터는 매우 의심됩니다. gcc를 -O3과 함께 사용하여 코드를 컴파일했으며 생성 된 어셈블리는 두 루프에서 동일합니다. 따라서 기계에서 관찰되는 시간의 차이는 부수적입니다.
적색 경보
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.