2009-03-06 2 views
5

std :: vector에 대한 질문이 있습니다.매 루프 반복마다 벡터를 삭제합니다. 가장 효율적인 방법은 무엇입니까?

나는 예측 벡터 크기를 예측하고 벡터에 대한 충분한 메모리를 미리 예약하면 메모리 사용량을 줄이는 데 많은 도움이 될 것입니다. 다음의

어느 낫다 :

for (...) { 
    std::vector<Type> my_vector; 
    my_vector.reserve(stuff_count); 
    // Do stuff , and append stuff to my_vector. 
} 

또는이 :

std::vector my_vector; 
for (...) { 
    my_vector.clear(); 
    my_vector.reserve(stuff_count); 
    // Do stuff , and append stuff to my_vector. 
} 

가장 적합한 말해, 또는 제발 물건을의 더 나은 방법이 있다면.

미리 감사드립니다.

+0

이것은 의견 유형 질문이 아닙니다. 특정 시스템의 차이를 측정해야합니다. –

답변

11

첫 번째 변형에서는 각 반복마다 벡터의 버퍼를 다시 할당합니다. 일반적으로 비용이 많이 듭니다. 두 번째 변형은 때때로 재 할당 만합니다. 두 번째 변형은 속도가 우선 순위이기 때문에 더 좋습니다.

요소의 수를 알 수있는 곳은 궁금합니다. 어쩌면 모든 반복에 대해 최대 요소 수를 빠르게 계산할 수도 있습니다. 버퍼 크기로 설정하고 재 할당 할 필요가 없습니다.

+0

이것은 대개 상당히 비쌉니다 : 프로파일 링이없는 대담한 진술입니다. C++ 메모리 할당자는 정확히 이런 유형의 상황을 위해 설계되었으므로 의심 스럽지만 (심지어 그 주장은 굵은 글이므로 테스트해야합니다). –

+0

글쎄, 우리는 한때 유사한 상황에서 프로필을 작성해야했습니다. 극단적 인 경우에 이러한 재 할당은 약 95 %의 시간을 차지했습니다. 버퍼가 할당되고 데이터가 복사되고 간략하게 분석 된 다음 버퍼가 삭제되었습니다. 그것은 다소 놀라운 것이 었습니다. – sharptooth

+0

이렇게하면 빠른 실행을 원할 경우 불필요한 재 할당을 피해야한다는 결론이 도출됩니다. – sharptooth

5

두 번째 것보다 약간 빨라질 수 있지만 첫 번째는 더 깨끗합니다.

+0

깨끗함은 괜찮습니다. 그러나 제 상황에서는 알고리즘이 최대한 많은 최적화가 필요하므로 정리는 중요하지 않습니다. 최적화되지 않은 테스트에서 10GB 메모리를 사용할 수 있습니다. – Nailer

+0

그러면 이런 질문을해서는 안됩니다 (모든 사람의 의견은 매우/틀릴 수도 있습니다). 코드를 프로파일 링하고 더 작은 데이터 세트에서 시간을 측정해야합니다. –

5

코드의 차이점은 간단하므로 두 방법을 모두 테스트하고 특정 응용 프로그램에 가장 적합한 방법을 확인하십시오.

1

유형을 구성/파괴해야하는 방식에 따라 약간 달라집니다. 그것은 파괴를 필요로하지 않는 POD 인 경우, 루프의 모든 소멸자를 호출하는) (맑은을 건너 뛰고 대신 정적 배열로 사용할 수 있습니다

std::vector<Type> my_vector(size); 
for (...) 
{ 
    int index = 0; 
    // Do stuff 
    my_vector[index] = some_value; 
} 

(경고 : 코드 안된)

+0

POD라면 어떤 경우에도 벡터가 파괴를 최적화 할 것으로 기대합니다. 성능에 대한 결론에 도달하기 전에 테스트하십시오. – jalf

+0

동의 함. (Jalf와) –

+0

이론 상으로는 맞습니다, Jalf. 당신이 일을 많이 망칠지도 모른다는 암시로 대답을 들려주십시오. 아마 거기에서 할 수있는 일이있을 것입니다. –

1

... 사전에 벡터에 대한 충분한 메모리를 예약하는 것은 나에게 메모리 사용

ERR을 줄일 수있는 많은 도움이 될 것입니다 ... 무엇?! 그건 전혀 말이되지 않습니다. 메모리를 예약한다고해서 메모리 사용이 줄어들지는 않습니다. 그것은 물건을 더 빠르게 만드는 일정한 재 할당의 필요성을 막습니다. 그러나 사용까지는 아무런 이득도 얻지 못합니다.

+0

실제로 사용 가능한 바이트 수는 동일하지만 가장 큰 할당 가능 청크는 더 작습니다. 적절한 크기가 될 때까지 반복해서 재 할당하면 결국 힙이 조각 나게됩니다. 결국. – xtofl

+0

그 위에는 벡터가 연속적인 메모리를 가져야하므로 현재 벡터를 더 이상 확장 할 수없는 경우 완전히 새로운 블록을 할당해야하며 이전 벡터는 복사되고 할당이 해제됩니다. 일시적으로 (oldsize + newsize) 메모리를 사용합니다. 거대한 메모리 요구 사항이 있으면 관련성이 있습니다. – Pieter

+0

벡터는 append 함수를 호출하고 다음 요소를위한 공간이 충분하지 않을 때 필요한 메모리의 두 배를 할당합니다. 즉, 100 개의 요소에 대해 충분히 큰 벡터가있는 경우 101 번째 요소를 추가하면 벡터는 200 개의 요소에 대해 충분한 메모리를 할당합니다. – Nailer

6

벡터 크기를 예측하고 미리 벡터에 충분한 메모리를 예약하면 메모리 사용량을 줄이는 데 많은 도움이됩니다.

점쟁이가 아닌 엔지니어처럼 행동하고 행동하십시오. 테스트를 만들고 그 차이를 측정하십시오.

0

많은 추가 작업이 필요한 경우 std :: vector 대신 std :: deque를 사용하고 "push_back"을 사용하십시오.

0

어때요?

std::vector<DataType> my_vector; 
my_vector.resize(sizeof(yourData)); 
memcpy(reinterpret_cast<char*>(&my_vector), &yourData, sizeof(yourData)); 
+0

왜 std :: copy()? –

1

두 번째 것은 루프를 통해 모든 용도의 최대 메모리, 즉 stuff_count 유형의 최대 크기를 사용합니다. std::vector::clear() does not necessarily free memory. 예를 들어 을 std::vector::clear() 전후에 호출하면 표준 준수 구현은 동일한 값을 반환 할 수 있습니다.

기껏해야 위 스키마로 메모리를 할당하는 횟수가 줄어 듭니다. 그러나 어느 시점에서라도 메모리 사용량을 줄이지는 않을 것입니다. 전체적인 효과는 동일하기 때문에,

std::vector<type>().swap(my_vector); 
my_vector.reserve(stuff_count); 

또는 첫 번째 해결책 : 메모리의 예약 된 양을 축소하려는 경우 벡터 스왑 관용구를 사용해야합니다.

관련 문제