2017-03-23 1 views
-1

그래서 현재 raytracing에 대해 읽고 있는데 개념을 이해하는지 직접 확인하기 위해 몇 가지 사항을 테스트하고 싶습니다. http://netpbm.sourceforge.net/doc/ppm.html에서 간단한 ppm 파일을 작성하는 방법을 찾았습니다.C++ 동적 배열 크기

저는 Visual Studio 2015를 사용하고 각 픽셀의 rgb 값을 2D 배열에 저장하고 있습니다. 이미지의 해상도는 720p이고 각 픽셀은 빨강, 녹색 및 파랑에 대해 3 개의 정수를 가지므로 배열은 int[720*1280][3]처럼 보입니다.

메모리의 총 사용량이 4 바이트 (2D 배열에 대한 포인터의 경우) + 720 * 1280 * (4 + 3 * 4) 바이트 (배열을 가리키는 720 * 1280 포인터의 경우) 3 정수로) 약 14MB입니다.

Visual Studio에서 메모리 사용량을 확인할 때 약 60MB의 메모리를 사용한다고합니다. 제가 묻고 싶은 것은 여분의 36 MB가 어디에서 오는 것입니까?

MAIN.CPP

#include <iostream> 

#include "PPM.h" 


int main(int argc, char **argv) 
{ 
    // WIDTH AND HEIGHT OF THE IMAGE 
    const int width = 1280; 
    const int height = 720; 

    // 3 RGB VALUES FOR EACH PIXEL 
    const int rgb = 3; 

    // CREATE A BUFFER TO HOLD THE DATA 
    int **data = allocateBuffer(width, height, rgb); 

    // FILL IN THE BUFFER 
    for (int y = 0; y < height; y++) 
    { 
     for (int x = 0; x < width; x++) 
     { 
      data[y*width + x][0] = x %255; 
      data[y*width + x][1] = y %255; 
      data[y*width + x][2] = 0; 
     } 
    } 

    // WRITE THE DATA TO A FILE 
    saveImage("Test.ppm", width, height, data); 

    // DELETE THE BUFFER 
    deleteBuffer(data, width*height); 

    // WAIT FOR INPUT TO EXIT 
    std::cout << "Press ENTER key to exit\n"; 
    std::getchar(); 
    return 0; 
} 

몇 즉 PPM.h

#pragma once 

// WRITES THE DATA TO THE FILE 
extern void saveImage(char *filename, int width, int height, int **data); 

// CREATES A BUFFER TO HOLD THE DATA 
extern int** allocateBuffer(int width, int height, int rgbAmnt); 

// RELEASES THE MEMORY 
extern void deleteBuffer(int **buffer, int size); 

PPM.cpp

#include "PPM.h" 
#include <fstream> 

// WRITES THE DATA TO THE FILE 
void saveImage(char *filename, int width, int height, int **data) 
{ 
    std::ofstream file; 
    file.open(filename); 
    file << "P3" << "\n" << width << " " << height << "\n255\n"; 
    for (int y = 0; y < height; y++) 
    { 
     for (int x = 0; x < width; x++) 
     { 
      file << data[y*width + x][0] << " " << data[y*width + x][1] << " " << data[y*width + x][2] << "\n"; 
     } 
    } 
    file.close(); 
} 

// CREATES A BUFFER TO HOLD THE DATA 
int** allocateBuffer(int width, int height, int rgbAmnt) 
{ 
    int size = width * height; 
    int **data = new int*[size]; 
    for (int i = 0; i < size; i++) 
    { 
     data[i] = new int[rgbAmnt]; 
    } 
    return data; 
} 

// RELEASE THE MEMORY 
void deleteBuffer(int **buffer, int size) 
{ 
    for (int i = 0; i < size; i++) 
    { 
     delete[] buffer[i]; 
    } 
    delete[] buffer; 
} 
+0

나는 당신의 프로그램이 단지 하나의 변수를 선언하는 것을 매우 의심한다. 둘째, 메모리 손상을 디버깅하는 데 사용되는 "가드 바이트"및 발생할 수있는 모든 패딩 바이트에 대한 추가 오버 헤드가 계산에 포함되지 않습니다. – PaulMcKenzie

+1

배열 선언을 주석 처리 한 다음 메모리 사용이 무엇인지 확인합니다. – Barmar

+0

미안 내 계산에 대해 생각한 후에 나는 메모리 사용량이 훨씬 더 낮았어야한다고 생각한다. (단지 1280 * 720 * 16) + 4는 약 14MB가되어야한다. Cureently 프로그램은 매우 작고, int와 C- 문자열을 선언 한 4 개의 함수 만 있습니다. 나는 배열을 할당하는 1 개의 함수와 그것을 삭제하는 1 개의 함수를 가지는 주된 기능을 가지고있다. 마지막 함수는 and ofstream을 사용하여 파일에 데이터를 씁니다. 코드를 추가 할 수 있는지 확인하려고합니다. –

답변

0

, 어디 갔지 n 메모리 블록을 요청하면 일반적으로 요청한 것 이상을 얻게됩니다. 비록 당신이 그것을 모르고있다.

이는 여러 가지 이유로 발생합니다. 첫째, 성능의 경우 : 메모리 블록이 인 경우 여러 프로세서가 더 빠르게 실행됩니다. 블록 주소가 일부 정수 (일반적으로 2의 거듭 제곱)의 배수임을 의미하는 일부 경계를 따라에 맞춰 정렬됩니다. 둘째, 입도가으로, 낮은 수준의 소프트웨어 (OS 및 프로그램의 런타임 라이브러리)가 최소 크기의 블록을 관리하는 것을 선호한다는 의미입니다. 3 번째로 관리 메모리 자체입니다. 즉, 하위 레벨 소프트웨어가 데이터 블록에 헤더 (접두어)와 예고편 (또는 접미사)을 추가합니다. 그들은 이러한 데이터 블록을 할당 및 해방시킬 수있는 정보를 가지며, 아마도 일부 확인을 할 것입니다.

예를 들어 부주의 또는 악성 프로그램에 의해 손상되지 않았는지 확인하기 위해 할당 된 데이터 블록의 크기, 다음 블록에 대한 포인터 및 헤더 및 예고편의 체크섬 등이 있습니다.

+0

답변 해 주셔서 감사합니다. 나는 당신이 메모리를 할당 할 때 약간의 패딩이 있다는 것을 읽었지만, 단지 그것이 단지 몇 바이트가 될 것이라고 예상했다. 어쩌면 내가 잘못 계산하고 실제로 사용되는 메모리의 양이 실제로 60 바이트에 가깝습니다. –

+0

allocateBuffer 루틴을 고려하십시오. 여기서 3-int 배열을 많이 할당합니다. 오버 헤드가 많습니다. 맞습니까? 그들 각각에 대해 패딩과 헤더 (그리고 아마도 트레일러)가 있습니다. 더 큰 메모리 덩어리에서이를 변환하고 포인터 연산을 사용하여 개별 구성 요소에 액세스 할 수 있습니다. 당신은 어떻게 생각하십니까? –

+0

코멘트를 읽은 후 버퍼를 1D 배열로 변경했고 이제 메모리 사용량이 약 11MB로 떨어졌습니다. 대단히 고마워. 가능한 한 1D 배열을 사용하면 메모리를 절약 할 수 있기 때문에 그렇게하는 것이 좋습니다. –