2011-08-01 2 views
1
나는 다음과 같은 유형의

메모리 사용량 - 예상대로 메모리 사용량을 감소하지 않았다 뜨는 이중 변환

template<class T> 
struct node 
{ 
    //some functions 
private: 
    T m_data_1; 
    T m_data_2; 
    T m_data_3; 

    node* m_parent_1; 
    node* m_parent_2; 
    node* m_child; 
} 

템플릿의 목적은 사용자를 활성화하는 것입니다있는 클래스의 수백만을 초기화하고

float 또는 double 정밀도를 선택하려면 node<float>을 사용하면 메모리 (RAM)가 적어집니다.

그러나 double에서 float으로 전환하면 예상대로 내 프로그램의 메모리 사용 공간이 줄어들지 않습니다. 나는

  1. 이 가능 컴파일러/운영 체제 내 수레에 필요한 (또는 더블로 저장)보다 더 많은 공간을 확보 있다는 두 가지 질문을해야합니다. 그렇다면, 어떻게 이런 일을 멈추게합니까? 64 비트 머신에서 리눅스를 g ++로 사용하고 있습니다.

  2. 모든 다른 클래스에서 사용되는 메모리 양을 결정할 수있는 도구가 있습니까? (즉, 일종의 메모리 프로파일 링) - 내가 생각하지 않은 다른 곳으로 메모리가 겹쳐지지 않도록하기 위해.

+0

sizeof 노드를 사용하십시오. 따라서 노드 크기는 이고 노드 크기는 입니다. – QuentinUK

답변

5

64 비트 용으로 컴파일하는 경우 각 포인터의 크기는 64 비트입니다. 이는 또한 64 비트로 정렬해야 할 수도 있음을 의미합니다. 따라서 3 개의 부동을 저장하면 4 바이트의 패딩을 삽입해야 할 수 있습니다. 따라서 12 바이트를 저장하는 대신 8 개만 저장할 수 있습니다. 포인터가 구조체 또는 끝 부분에 있는지 여부에 관계없이 채우기가 계속됩니다. 정렬을 계속 유지하기 위해 배열에 연속 구조체를 넣으려면이 작업이 필요합니다.

또한 구조는 주로 3 개의 포인터로 구성됩니다. 저장 한 8 바이트는 48 바이트 오브젝트에서 40 바이트 오브젝트로 이동합니다. 그것은 엄청난 감소가 아닙니다. 64 비트 용으로 컴파일하는 경우에도 마찬가지입니다.

32 비트 용으로 컴파일하는 경우 36 바이트 구조에서 12 바이트를 절약 할 수 있습니다. 이는 백분율별로 더 좋습니다. double이 8 바이트로 정렬되어야하는 경우 잠재적으로 더 많습니다.

새/malloc을 호출

, 그것은 반드시 1 OS가 메모리를 할당 할 수있는 전화 1에 해당하지 않는 : 니콜이 만드는 유효한 점에 addtion에서

+0

주목할만한 점은이 경우 패딩은 데이터 노드 포인터 사이에 추가되지만 패딩은 '노드 n [2]'에 포인터가 올바르게 입력되도록 계산되므로 필드의 순서를 변경하면 도움이되지 않습니다. aligned - 노드를 먼저 넣으면 데이터는 struct의 끝에 패딩을 가져옵니다. –

1

. 이는 비싼 시스템 호출 횟수를 줄이기 위해 힙 관리자가 요청한 것보다 많은 것을 할당 한 다음 new/malloc을 호출 할 때 힙을 "하위 할당"하기 때문입니다. 또한 메모리는 한 번에 4KB 만 할당 할 수 있습니다 (일반적으로 최소 페이지 크기). 근본적으로 미래의 할당 속도를 높이기 위해 현재 적극적으로 사용되지 않는 메모리 덩어리가 할당되어있을 수 있습니다.

것은 직접 질문에 대답하려면 :

1) 예, 매우 가능성이 더 많은 메모리를 할당 할 런타임 당신은 요구 - 그러나이 메모리는, 그것은 미래 뉴스/mallocs에 사용됩니다 낭비 만하지 않습니다됩니다 여전히 "작업 관리자"또는 사용하는 도구에 표시됩니다. 아니요, 수레를 두 배로 늘리지는 않습니다. 할당량이 많을수록이 가장자리 조건이 크기 차이의 원인이 될 가능성이 적어지고 Nicol의 항목이 우세합니다. 할당 횟수가 적 으면이 항목이 지배적 일 수 있습니다 ("큰"및 "작은"은 OS 및 커널에 전적으로 의존 함).

2) Windows 작업 관리자는 할당 된 전체 메모리를 제공합니다.WinDbg와 같은 것은 실제로 런타임에 할당 된 가상 메모리 범위 청크 (일반적으로 트리로 할당 됨)를 제공합니다. Linux의 경우이 데이터는 프로세스와 관련된/proc 디렉토리의 파일 중 하나에서 사용 가능할 것으로 예상됩니다.

3

다른 답변은 불일치의 원인에 대해 정확합니다. 그러나 x86/x86-64의 포인터 (및 다른 유형)는 이 아니며은 정렬해야합니다. GCC가 성능을 향상시키는 것이 성능 향상이라는 것입니다. GCC가 기본적으로 성능을 유지하는 이유입니다.

그러나 GCC는이 통제를 발휘하도록하는 "포장"속성을 제공합니다

내 시스템에서
#include <iostream> 

template<class T> 
struct node 
{ 
private: 
    T m_data_1; 
    T m_data_2; 
    T m_data_3; 

    node* m_parent_1; 
    node* m_parent_2; 
    node* m_child; 
} ; 

template<class T> 
struct node2 
{ 
private: 
    T m_data_1; 
    T m_data_2; 
    T m_data_3; 

    node2* m_parent_1; 
    node2* m_parent_2; 
    node2* m_child; 
} __attribute__((packed)); 

int 
main(int argc, char *argv[]) 
{ 
    std::cout << "sizeof(node<double>) == " << sizeof(node<double>) << std::endl; 
    std::cout << "sizeof(node<float>) == " << sizeof(node<float>) << std::endl; 
    std::cout << "sizeof(node2<float>) == " << sizeof(node2<float>) << std::endl; 
    return 0; 
} 

(- 64, g ++ 4.5.2),이 프로그램의 출력 :

sizeof(node<double>) == 48 
sizeof(node<float>) == 40 
sizeof(node2<float>) == 36 

물론 "속성"메커니즘과 "압축 된"속성 자체는 GCC와 관련이 있습니다.