2012-06-14 2 views
2
#include <iostream> 
#include <cassert> 
#include <vector> 
#include <ctime> 
#include <cstdlib> 
#include <Windows.h> 

using namespace std; 

char randomLetter() 
{ 
    srand(time(0)); 
    char rValue; 

    while(1) 
    if((rValue=(rand()/129)) > 31) 
     return rValue; 
} 


int main() 
{  
    vector<char> meegaString; 

    for(int i=0; i < 10000000000; i++) 
    { 
     meegaString.push_back(randomLetter()); 

       if(!(i%10000000)) 
      cout<<"There are: " <<i+1<<" chars in the list"<<endl; 

    } 

    system("pause"); 
    return 0; 
} 

이 프로그램을 실행하기 전에 RAM 사용량은 약 2500/8000 MB입니다. 그것은 3200에 관해서 는 다음과 같은 예외가 발생합니다 :왜 RAM과 CPU를 사용하도록 설계된 프로그램이 모든 RAM과 CPU를 사용하지 않습니까?

자원 gormandizer.exe에서 0x773c15de에서

처리되지 않은 예외 : 마이크로 소프트 C++ 예외 : 메모리 위치 0x0045f864에서 표준 : : bad_alloc 뿐이다 ..

1) 64 비트 OS에서 작동하지만이 프로그램이 사용 가능한 전체 메모리를 채우지 못하는 이유는 무엇입니까?

2) 왜 프로세서의 26 % (인텔 코어 i5) 만 사용 되었습니까?

+4

나는 벡터가 연속적인 메모리 블록을 요구할 수도있다. 따라서 사용 가능한 메모리 양에 관계없이 필요한 크기의 메모리 블록을 사용할 수 있어야합니다. – hmjd

+0

벡터는 링크 된 목록이 아니라 동적 배열입니까? 당신은 나를 많이 놀라게했습니다 :) – 0x6B6F77616C74

+2

C++ 표준에서 : _ 벡터 요소는 연속적으로 저장됩니다 .. .. – hmjd

답변

4
  1. 상술 한 바와 같이, 벡터의 요소는 연속적으로 저장된다. 또한 std::vector 구현에 사용 된 메모리 할당 알고리즘에 따라 미리 메모리를 미리 할당하려고 시도하고 있습니다. malloc/new 호를 줄이기 위해 사용되는 것보다 많은 메모리를 할당합니다. 따라서 32 비트 OS가 지원할 수있는 것보다 더 많은 메모리를 요청할 수 있습니다 (64 비트 프로세스가 작동하는 이유를 설명하지만 32 비트 프로세스는 메모리가 충분 함에도 불구하고 유효한).

  2. 귀하의 프로세스가 4 개의 코어 중 하나에서 실행되고있어 매우 바쁩니다. 따라서 CPU 시간의 약 25 %를 차지합니다. 다른 프로세스가 나머지 프로세스를 구성합니다.

참조 : Being Smart About Vector Memory Allocation

+1

+1 for forward allocation. @kutacz, 루프 이전에'reserve()'가 흥미롭고 더 많은 문자를 처리하는지 점검 할 수 있습니다. – hmjd

0

vector 클래스 템플릿 메모리의 연속 블록을 필요로하는 동적 배열을 구현한다.

주제를 닫으려면 list 컨테이너를 사용할 수 있지만 stack이 가장 좋은 해결책 인 것 같습니다. 그러나 목록 또는 스택 중 하나라도 여전히 동일한 오류 (현재 인근 4600MB)로 인해 충돌합니다. 비슷한 것처럼 보이지만 잘못된 데이터 구조가 잘못 선택된 것은 아닙니다. 이것은 32 비트 응용 프로그램에 사용할 수있는 메모리가 매우 제한되어 있기 때문에 발생합니다. 따라서이 프로그램을 완전히 밀어 넣으려면 x64 플랫폼에서이 프로그램을 컴파일하십시오. 우리는 자신을 표현하는 약간의 자유를 가지고있는 경우 안토니 - 아놀드의 대답

#include <iostream> 
#include <stack> 
#include <ctime> 
#include <cstdlib> 


using namespace std; 

char randomLetter() 
{ 
    srand(time(0)); 
    char rValue; 

    while(1) 
    if((rValue=(rand()/129)) > 31) 
     return rValue; 
} 


int main() 
{  
    stack<char> meegaString; 

    for(int i=0; i < 10000000000; i++) 
    { 
     meegaString.push(randomLetter()); 

       if(!(i%10000000)) 
      cout<<"There are: " <<i+1<<" chars in the list"<<endl; 

    } 




    system("pause"); 
    return 0; 
} 
+0

스택은 std :: deque를 사용하도록 기본 설정된 컨테이너 어댑터 일 뿐이므로 "최상의 솔루션"은 deque가 될 것입니다. 그리고 deque가 청크로 할당되기 때문에 이유를 설명 할 수도 있습니다. – PlasmaHH

2

이 잘못된 것이 아니라 아직 행방 불명 뭔가가있다.

코어 i5가 쿼드 코어 (모두 i5의 쿼드 코어입니까?) 인 경우 25 %는 코어 중 하나 (즉, 프로세스가 진행중인 코어)가 거의 100이라고 제안 할 수 있습니다 % 통화 중이고 나머지는 주로 유휴 상태입니다. anthony-arnold의 답변과는 달리, 25 %는 다른 프로세스가 나머지 75 %를 차지하고 있음을 나타내지 않고, 사용 가능한 CPU 시간의 75 %가 단순히 낭비된다는 것을 나타냅니다. 다시 말하지만 CPU가 멀티 스레드 테스트 응용 프로그램없이 쿼드 코어 인 경우 테스트 응용 프로그램이 전체 시스템의 25 % 이상을 사용할 수 없게됩니다.

메모리 부족 문제를 해결하고 메모리 할당 조각화 및 기타 오버 헤드를 줄이려는 경우이를 발견했습니다. 다른 사람들이 제안했듯이, 앱은 32 비트 앱으로 제작 된 것 같습니다. 64 비트 OS에서 실행되는 경우에도 응용 프로그램은 32 비트 주소 공간에서 보유 할 수있는 한계 인 4Gb를 초과하여 주소를 지정할 수 없습니다.그렇더라도 OS, 프로그램 및 공유 라이브러리 공간, 스택 공간 및 힙 공간 오버 헤드뿐만 아니라 다른 것들에 할당 된 힙 공간을 위해 예약 된 가상 주소 공간을 포함하여 많은 오버 헤드가 있습니다. 따라서 meegaString 벡터는 심지어 4Gb에 거의 근접하지 않습니다. 아마 2Gb에 가깝지 않을 것입니다 (아마도 대형 주소 공간 인식 응용 프로그램으로 빌드 된 경우 2Gb를 약간 넘을 수 있습니다).

anthony-arnold가 언급 한 "forward allocation"포인트와 관련하여 모든 STL 컨테이너는 상각 된 작동 시간을 약속합니다. std :: vector 클래스는 평균적으로 (amortized) push_back() 연산이 일정 시간 (즉, O (1)) 일 것을 약속합니다. 즉, 내용이 커질수록 &이 더 커지고 push_back() 더 이상 & 걸릴하지 않습니다 (만약 그렇다면 O (n)이 될 것입니다). 종종 push_back()은 push_back()이 컨테이너의 데이터가 현재 할당 된 공간을 초과하게하고, 재 할당을 수행하고 현재 내용을 다음과 같이 이동해야하기 때문에 O (1) 이상으로 push_back 새 위치를 찾고 이전 내용을 삭제합니다. OS와의 협력을 통해 잘 구현 된 맞춤형 STL 구현은 가상 메모리와 MMU를 사용하여 트릭을 재생하는 것보다 훨씬 효율적으로 수행 할 수 있으므로 실제로 내용을 이동할 필요가 없으므로 OS에 알려 데이터의 가상 메모리 페이지를 새 위치로 매핑하는 MMU는 완전히 다른 문제이며 어쨌든 걱정할 필요가 없습니다. 왜냐하면 뒤에서 일어날 것이기 때문입니다. 어떤 경우에는 od (1) push_back() 시간을 약속 할 수있는 유일한 방법이기 때문에 std :: vector 클래스는 새로운 할당을 수행 할 때 필요한 것보다 큰 메모리 블록을 "미리 할당"해야합니다. push_back()을 할 때마다 새로 할당 된 버퍼로 내용을 이동해야한다면 push_back()의 ​​시간 복잡도는 O (1)이 아닌 O (n)이됩니다. 왜냐하면 push_back()는 벡터의 데이터가 클수록 길어질수록 더 길어질 것입니다 (&).

관련 문제