2010-06-24 5 views
5

Hei 커뮤니티,포인터 삭제 시간

포인터 삭제와 관련하여 작은 질문이 있습니다.

Dimension 1024x1024의 포인터 - 투 - 포인터 행렬로 작업하고 있습니다. 동적으로 생성하기 때문에 프로그램 끝에 할당 된 공간을 삭제합니다. 그러나 일반적인 루프에서이 작업을 수행하는 데는 상당한 시간이 걸리므로 프로세서의 클럭 속도를 사용하여 약 2 초를 측정했습니다. 그리고 프로그램이 단지 15 초 만에 실행될 때 2 초는 더 커집니다 : 더하기 : 할당 된 포인터를 사용하는 함수는 한 번 이상 호출됩니다 ....

time=clock(); 
for(i=0;i<xSize;i++){   //xSize is dynamic, but 1024 for the measurement 
    delete [] inDaten[i]; 
    delete [] inDaten2[i]; 
    delete [] copy[i]; 
} 
delete inDaten; delete inDaten2; delete copy; 
time=clock()-time; 
    time/=CLOCKS_PER_SEC; 

는 항상 긴 포인터를 삭제되어

여기에 측정을 포함하여 코드의 측정 시간이 중요한 부분은 무엇입니까? 아니면 그냥 잘못하고있는 것입니까?

여기 누군가 나를 도와 줄 수 있기를 바랍니다. 더 복잡한 프로그램을 더 빠르게 실행하도록 최적화했기 때문에 2 초 분량의 코드를 사용할 수 없습니다. 그것은 다른 모든 부분에 비해 너무 느립니다. 하지만 여전히이 코드를 동적으로 구현할 수 있어야합니다. SmartPointers는 도움이 될 수 있지만, 정확하게 이해한다면, 그들은 또한 다른 시간에 - 스스로를 삭제할 시간이 필요합니다 ...

답해 주셔서 감사합니다!

Baradrist

편집 : 난 그냥 내가 릴리스 모드에서 컴파일하지 않았기 때문에이 삭제-계산을 측정하는 것은 매우 느린 것을 발견했다. 디버거가 작동하기 때문에, 나는 두통을 낳은 (끝내 비현실적인) 숫자를 측정했다. 최종 프로그램은 자동으로 최적화되므로 삭제에 더 이상 시간이 거의 들지 않습니다.

어쨌든 : 모든 유용한 답변 주셔서 감사합니다! 그들은 내게 많은 여분의 지식과 생각할 것들이있어 !!!!

+1

'inDaten','inDaten2' 및'copy'에있는 객체의 유형은 무엇입니까? 그들은 단지 int 또는 그와 비슷한 것입니까, 아니면 진짜 객체입니까? –

+1

모든 것을 동적으로 할당해야합니까? 이렇게 많은 * 별개의 할당이 필요합니까? 적은 수의 할당으로 데이터를 저장하도록 프로그램을 다시 작성할 수 있습니까? – jalf

+0

내 netbook에서 double []을 삭제해도 다음 시계 틱으로 이동하지 않으므로 디버거가 연결되어 실행 중이거나 어레이의 요소 소멸자에서 비싼 작업이 진행 중입니다. –

답변

3

또한 소멸자가 사소하지 않으면 시간을 추가하는 배열의 각 요소에 대해 소멸자를 호출합니다.

그 외 - 예, 동적 메모리 할당은 상대적으로 비용이 많이 듭니다. 당신이 그것을 용납 할 수 없다면 - 더 큰 크기의 블록을 더 적게 배치하거나 시간이 중요한 일에 동적 할당없이 시도하십시오.

스마트 포인터는별로 도움이되지 않습니다. 내부에서 동일한 할당 취소 작업을 수행합니다. 속도 향상을위한 것이 아니라 설계 편리 성을위한 것입니다.

1

프로그램 끝에서 삭제하고 소멸자가 실행되는 데 문제가 없으면 단순히 삭제하지 마십시오. 메모리는 OS에 의해 할당이 취소됩니다. 그렇지 않은 경우에는 단일 포인터 삽입 배열을 사용하지 마십시오. 삭제 시간을 단축하는 것 외에도 참조의 지역성이 향상됩니다.

+2

OS가 메모리를 전혀 사용하지 않는다고 보장 할 수는 없습니다. – Yacoby

+3

@ Yacoby : OS 자체가 그러한 보증을 제공하지 않는 한. 어떤 현대 (데스크탑) OS가. – jalf

+0

OS가 종료 할 때 OS가 프로세스 메모리를 정리하는지 여부와 상관없이, 그런 버팀대에 의존하는 것은 여전히 ​​나쁜 습관입니다. 빠른 할당 해제에 더 적합한 할당자를 사용하는 것이 더 좋으며, 그리고/또는 코드 해제를 최소화하기 위해 코드를 재 설계하는 것이 더 좋습니다 (물론 누출을 도입하지 않고). – Void

2

여기에 흥미로운 스레드 "Memory Allocation/Deallocation Bottleneck?"

할당 및 해제 시간이 오래 걸릴 따라서 당신이 가지고있는 가장 일반적인 비용이 많이 드는 작업 중 하나입니다. 이것은 힙 관리가 많은 것들을 돌봐야하기 때문입니다. 보통 디버그 모드에서 메모리 블록에 대한 검사가 많이 있습니다. 릴리스 구성에서 같은 시간을 보내고 있다면 놀랄 것입니다. 일반적으로 최소한 2의 중간에 요소가 있습니다. 개인 힙을 사용하면 작업을 크게 늘릴 수 있습니다.동일한 크기의 객체를 항상 할당하면 메모리 풀이 가장 좋은 대안이 될 수 있습니다.

0

파괴 시간을 줄일 수 있도록 자신의 메모리 할당 방법을 만들어보십시오.

예를 들어 Os에서 메모리 블록을 요청하고 배열을 할당하여 단일 블록에서 전체 블록을 해제 할 수 있습니다.

1

문제는 데이터 구조에있는 것처럼 보입니다. 왜 그렇게 많은 동적 할당이 필요합니까? 할당 횟수를 줄이기 위해 할 수있는 일은 무엇입니까?

포인터를 비우는 데 2 ​​초가 걸리는 경우 할당하는 데 많은 시간이 소요될 가능성이 큽니다.

프로그램을 빠져 나가기 만하면 프로그램을 종료 할 수 있습니다. C++은 할당 된 메모리가 어떻게 될지에 대해서는 보장하지 않지만 OS가 아마도 그렇습니다. 따라서 이라는 용어로는 실행 시간을 2 초 단축하는 쉬운 방법 일 수 있습니다.

하지만 여전히 할당 시간이 2 초를 넘습니다.

가장 좋은 방법은 데이터를보다 잘 구조화하는 것입니다. 매트릭스가 현재 어떻게 구성되어 있는지 보여줄 수 있습니까?

+0

1 차원 매트릭스를 사용하면 시간을 절약 할 수 있습니다! 당신은 구조와 관련하여 옳습니다. 행렬에는 회색 음영이 있습니다 (1024x1024 등). 여전히 : 할당은 할당 해제보다 훨씬 빠릅니다 (측정 결과) – Baradrist

0

모든 빠른 답변에 대해 고마워요 !!! 밖에있는 누군가가 도움이된다는 것을 보는 것이 좋다.). 그래도 내 문제는 내가 결국이 수행되지 않는 작은 하위 프로그램에서 임시 매트릭스로 동적 배열이 필요하기 때문에 나는이 시간의 손실을 다뤄야 만하는 것처럼 보입니다.

어쨌든 : 다시 한 번 감사드립니다 !! 그리고 좋은 하루 되세요! 객체가 배열에서 지적 경우 Baradrist

+0

1 차원 행렬을 사용하면 트릭을 수행해야합니다. - 감사합니다! – Baradrist

0

는 많이 크게 런타임을 개선하기 위해 무엇을 할 수가 먼저 해결하지 않고이없는 비 사소한 소멸자가 있습니다. 그렇지 않으면 :

대신 그들에게 크기 isize*isize의 배열을하지 왜 크기 isize의 배열에 대한 포인터의 크기 isizeinDaten, inDaten2 and copy 배열을 만드는 대신에 개별 항목을 주소의

: array[i][j]array[i*isize+j]와이를 해결. 그런 식으로 하나의 전화 delete []으로 정리할 수 있습니다.

1

이 있어야하지 :

로 사용했기 때문에
delete [] inDaten; delete [] inDaten2; delete [] copy; 

, 그들은 분명히 배열입니다. (적어도 그들은 너무 너무, 당신은 충분히 컨텍스트를 제공하지 않은 것으로 나타납니다).

+0

예, 이미 변경되었지만 시간 수 =는 변경되지 않습니다. – Baradrist

0

최적화는 청크로 메모리를 할당하고, 새로운 포인터로 개별 포인터를 할당하고 삭제시 전체 청크를 삭제하는 것입니다.

이 옵션은 암시 적으로 이 새로운 객체로 할당 된 각 객체의 소멸자을 호출하지 않으므로주의해야합니다.

1

배열의 객체가 얼마나 큰지는 알 수 없지만 충분히 큰 경우 메모리의 일부가 스왑 아웃되어 다시 스왑 될 필요가있을 수 있습니다. 프로세스 공간), 그리고 그것은 당신이보고있는 시간을 일으키는 것입니다.

0

메모리 할당/할당 해제가 병목 현상이라고 판단한 경우이를 빠르게 처리하려면 먼저 배열에 연속 버퍼를 사용하는 것이 가장 좋습니다. 2 차원 배열처럼 그것들에 접근하는 행렬 인터페이스를 제공 할 수 있습니다.

// Rudimentary Implementation 
template <class T> 
class SquareMatrix 
{ 
public: 
    explicit SquareMatrix(int i_size): 
     size(i_size), mat(new T[i_size * i_size]) {} 

    ~SquareMatrix() 
    { 
     delete[] mat; 
    } 

    // could also be column depending on row-major/col-major 
    T* operator[](unsigned int row) 
    { 
     return mat + row * size; 
    } 

    // could also be column depending on row-major/col-major 
    const T* operator[](unsigned int row) const 
    { 
     return mat + row * size; 
    } 

private: 
    unsigned int size; 
    T* mat; 
}; 

세 번째 행렬 대신 두 번째 행렬은 필요한 모든 데이터가있는 구조로 구성된 하나의 행렬입니다. 이것은 튜플의 한 행렬이 게시 한 코드의 경우처럼 보이는 것으로 충분합니다.

하드 코어로 가고 다중 행렬을 필요로한다면,이를 위해 자체 메모리 할당기를 작성하십시오. 한 번에 여러 행렬에 메모리를 할당하고 새로운 배치를 사용하여 간단히 구성 할 수 있습니다. 메모리 할당자를 작성하는 것이 간단한 작업이 아니기 때문에이 작업을 수행하려면 추가 읽기 및 연구가 필요합니다. 정렬과 같은 문제를 고려해야하지만 가장 빠른 방법입니다.

타이밍 테스트에 의존하는 대신 프로파일 러를 잡아 코드의 적절한 콜 그래프 분석을 수행하는 것이 좋습니다. 이렇게하면 얼마나 많은 시간을 보내고 있는지 정확하게 알 수 있습니다. 예를 들어, 행렬에있는 객체의 생성/제거가 가능한 한 저렴하지는 않을 수 있습니다.

명백한 알고리즘의 비효율적 인 부분이 없기 때문에, 매우 잘 알고있는 프로그래머조차도 코드의 병목 현상에 대해 종종 부정확합니다. 효율성이 중요한 관심사 인 경우 프로파일 러는 가장 친한 친구입니다.

0

매트릭스에서 포인터로 참조되는 모든 객체가 동일한 유형 (또는 적어도 동일한 크기) 인 경우 하나의 큰 메모리 덩어리를 할당하여 모두 유지하고 내부에서 초기화 할 수 있습니다.