2017-01-31 1 views
4

작은 배열 (~ 4096 Byte)을 정렬하고 출력 파일에 쓰는 두 개의 스레드를 실행해야하는 간단한 프로그램을 작성했습니다. 입력 데이터는 하나의 큰 파일 (~ 4Gb)에 들어 있습니다. 컴퓨터의 메모리는 128MB입니다. 난 그냥 빈 메인 함수를 실행 14MB의 메모리를 사용하는 것으로 나타났습니다. 빈 함수 응용 프로그램으로 std :: thread를 실행하면 스레드 당 ~ 8MB가 사용되기 시작합니다. 하지만 동적 메모리 할당 프로그램을 하나만 만들면 스레드 당 약 64MB가 사용되기 시작합니다. 나는 너무 많은 기억을 쓸 수있는 것이 무엇인지 이해하지 못한다. 이 크기를 어떻게 제어 할 수 있습니까? 그리고 일부 시스템 기본 할당을 최소화하기 위해 동적 메모리를 할당하는 방법은 무엇입니까?빈 함수를 사용하여 std :: thread를 실행하는 데 많은 메모리가 필요합니다.

  • 시스템 : 우분투 14.04.3
  • 컴파일러 : GCC 4.8.4
  • 컴파일러 옵션 : '-std = C++ 11 -03 -pthread'

  • 이것은 코드 예제입니다.

    void dummy(void) 
    { 
        std::vector<unsigned int> g(1); 
        int i = 0; 
        while(i<500000000) 
        { 
         ++i; 
        } 
    } 
    
    int main(void) 
    { 
        std::thread t1(&dummy); 
        std::thread t2(&dummy); 
        std::thread t3(&dummy); 
        t1.join(); 
        t2.join(); 
        t3.join(); 
        return 0; 
    } 
    
+0

다른 할당자를 사용해보십시오. jemalloc, tcmalloc. –

+2

프로그램에서 사용한 메모리 양을 어떻게 결정 했습니까? –

+1

나는 귀하의 조치를 신뢰하지 않습니다. 어떻게 메모리 사용량을 찾았습니까? – SergeyA

답변

7

모든 스레드마다 자체 스택이 있습니다. Linux에서 기본 스택 크기는 8MB입니다. 처음으로 메모리 할당을 시작하면 힙 메모리 할당자가 실제로 큰 덩어리를 앞쪽에 예약 할 수 있습니다. 이 은보고있는 스레드 당 64MB를 설명합니다.

즉, "할당 됨"이라고 말하면이 메모리가 실제로 사용된다는 의미는 아닙니다. 할당은 프로세스의 가상 메모리 공간에서 발생합니다. ps을 실행할 때 열 VSZ 아래에 표시되거나 top을 실행할 때 VIRT 열 아래에 표시됩니다. 그러나 리눅스는 어쨌든 할당 된 메모리의 대부분을 사용하지 않을 것임을 알고 있습니다. 따라서 가상 블록 메모리를 할당하는 동안 Linux는 프로세스가 실제로 해당 메모리에 쓰기를 시작할 때까지 실제 메모리 인을 할당하기 위해 메모리를 할당하지 않습니다. 프로세스에서 사용하는 실제 실제 메모리 양은 ps의 경우 RSS이고 top의 경우 RES 인 경우입니다. Linux는 실제 메모리가있는 것보다 많은 가상 메모리를 할당 할 수 있습니다.

실제 메모리가이 아니더라도 32 비트 시스템에 8MB의 가상 메모리를 할당하는 많은 스레드가있는 경우 가상 메모리가 부족할 수 있습니다 프로세스 공간 (2GB 단위). C++의 스레드 라이브러리는 스택 크기를 변경할 수 없지만 C pthreads 라이브러리는 pthread_attr_setstacksize()을 사용하여 조정 한 pthread_attr_tpthread_create()에 제공하여이 작업을 수행 할 수 있습니다. this stackoverflow question도 참조하십시오.

+0

시스템에 총 128MB RAM이있는 경우 프로세스의 주소 공간이 부족해질 가능성은 거의 없습니다. Linux는 먼저 RAM이 부족할 것입니다. – MSalters

+0

@MSalters : Linux는 메모리를 과도하게 사용하므로 RAM이 부족하기 전에 주소 공간이 부족할 수 있습니다. –

+0

이론상으로는 약 80MB의 RAM (20K 페이지)과 2048MB의 주소 공간 (512K 페이지)을 사용하면 엄청난 오버 커밋이 필요합니다. – MSalters

0

위의 설명에서 ulimit -s에 대해보고 한 값에 따르면 스레드가 빈 주인 경우에도 스레드가 여전히 스택을 할당하고 있음을 알 수 있습니다. 스레드에서 실행되는 함수 호출은 스택이 x86에 있다고 가정 할 때 리턴 주소를 전달해야합니다.

@Karrek SB가 올바른 방향으로 향하고 있습니다. 사용중인 할당자는 프로그램의 힙 크기에 영향을 줄 수 있습니다. brk 또는 sbrk에 대한 반복 호출을 피하기 위해 할당자는 일반적으로 더 큰 초기 메모리 블록을 요청합니다. 할당자를 처음 초기화 할 때 4, 8, 32, 64 등과 같은 일반적인 페이지 경계를 따라 잘 정렬되는 값은 MB 순서로 값을 예상하는 것이 무리가 아닙니다.

할당 된 메모리 양을 제어하려면 결과가 다를 수 있습니다. 할당자가 mallopt 기능을 지원하는지 확인하십시오. 약간의 시행 착오를 통해 전반적인 메모리 사용 공간을 줄일 수 있습니다. 그렇지 않으면, 당신은 항상 자신의 할당자를 구현할 수 있습니다.

관련 문제