programing

메모리를 2의 거듭제곱으로 할당하는 것이 더 나을까요?

lastcode 2023. 7. 16. 13:35
반응형

메모리를 2의 거듭제곱으로 할당하는 것이 더 나을까요?

가 용할때를 사용할 때.malloc()메모리를 할당하기 위해서, 우리는 2의 거듭제곱의 크기를 주어야 합니까?아니면 우리가 필요한 정확한 사이즈를 주는 건가요?
맘에 들다

//char *ptr= malloc( 200 ); 
char *ptr= malloc( 256 );//instead of 200 we use 256

2의 거듭제곱인 사이즈를 주는 것이 더 낫다면, 그 이유는 무엇입니까?왜 더 나은가요?

감사해요.

편집

제가 혼란스러워 하는 이유는 Joel의 블로그 Back to Basics의 인용문을 따른 것입니다.

스마트 프로그래머는 크기가 2배인 메모리 블록을 항상 할당하여 malloc의 잠재적인 중단을 최소화합니다.4바이트, 8바이트, 16바이트, 18446744073709551616바이트 등입니다.레고를 가지고 노는 사람이라면 누구나 직관적이어야 하는 이유로, 이것은 자유 체인에서 일어나는 이상한 파편화의 양을 최소화합니다.이렇게 공간을 낭비하는 것처럼 보일 수도 있지만, 공간의 50% 이상을 낭비하지 않는 방법도 쉽게 확인할 수 있습니다.따라서 프로그램이 필요한 메모리의 두 배 이상을 사용하지 않습니다. 이는 큰 문제가 아닙니다.

죄송합니다, 제가 위의 견적서를 더 일찍 게시했어야 했습니다.죄송합니다!

답변은 않은 생각이라고 , 에서 조엘의이 더 입니다. 그러면 어떤 시나리오에서 Joel의 요점을 따르는 것이 더 낫습니다.malloc()왜 그런 말을 했을까요?위의 인용된 제안은 이제 쓸모가 없습니까?

설명해 주세요.
합니다.

필요한 크기만 정확히 말씀해 주세요.2의 거듭제곱 크기가 "더 나은" 유일한 이유는 더 빠른 할당 및/또는 메모리 조각화를 방지하기 위해서입니다.

의 자명하지 않은 단, 사한것아닌경우이소▁however.malloc효율성과 관련된 구현은 적절한 경우와 시기에 내부적으로 이러한 방식으로 할당을 반올림합니다.여러분은 malloc를 돕는 것에 대해 걱정할 필요가 없습니다. malloc은 스스로 잘 할 수 있습니다.

편집:

Joel on Software 기사에 대한 귀하의 인용문에 대한 답변으로, 해당 섹션에서 Joel의 요점은 (인용한 단락에 이어지는 맥락 없이는 정확하게 식별하기가 어렵습니다) 버퍼를 자주 재할당할 것으로 예상되는 경우에는 추가적으로 재할당하는 것이 아니라 곱셈적으로 재할당하는 것이 좋습니다.사실, 이것은 정확히 그것입니다.std::string그리고.std::vector(다른 것들 중에서) C++의 클래스들은 합니다.

이것이 개선되는 이유는 당신이 도와주기 때문이 아닙니다.malloc메모리 할당은 비용이 많이 드는 작업이며 수행 횟수를 최소화하려고 하기 때문입니다.조엘은 시간-공간 트레이드오프의 개념에 대한 구체적인 예를 제시하고 있습니다.그는 필요한 메모리 양이 동적으로 변경되는 많은 경우에 정확하게 반복적으로 작업하는 데 필요한 시간을 절약하기 위해 필요한 공간을 낭비하는 것이 좋다고 주장합니다.n 바이트, 때마다 필할때메모바이수트리마다요,▁of수▁bytes.n더 많은 바이트.

승수가 2일 필요는 없습니다. 필요한 만큼 최대 3배의 공간을 할당하여 3의 거듭제곱을 할당하거나, 필요한 만큼 최대 57배의 공간을 할당하여 57배의 거듭제곱을 할당할 수 있습니다.과도한 할당을 수행할수록 재할당 빈도는 줄어들지만 메모리 낭비는 늘어납니다.필요한 만큼 최대 두 배의 메모리를 사용하는 2의 거듭제곱으로 할당하는 것은 필요한 것이 정확히 무엇인지에 대한 더 나은 아이디어가 없을 때까지 좋은 시작점 트레이드오프입니다.

그는 지나가는 말로 이것이 "자유 체인의 파편화"를 줄이는 데 도움이 된다고 언급하지만, 그 이유는 정확한 크기보다는 할당의 수와 균일성 때문입니다.우선, 메모리 할당 및 할당 해제 횟수가 많을수록 할당하는 크기에 관계없이 힙이 조각날 가능성이 높아집니다.두 번째로, 동일한 곱셈 크기 조정 알고리즘을 사용하여 동적으로 크기를 조정하는 버퍼가 여러 개 있는 경우, 하나의 크기가 32에서 64로 조정되고 다른 하나의 크기가 16에서 32로 조정되면 두 번째 재할당이 이전의 첫 번째 재할당에 적합할 수 있습니다.하나의 크기가 25에서 60으로 조정되고 다른 하나의 크기가 16에서 26으로 조정된다면 그렇지 않을 것입니다.

다시 말씀드리지만, 할당 단계를 한 번만 수행할 경우에는 그가 말하는 어떤 것도 해당되지 않습니다.

데블의 옹호자 역할을 하기 위해 Qt는 다음과 같습니다.

QString 문자열에 15000자를 추가한다고 가정합니다.그런 다음 4, 8, 12, 16, 20, 52, 116, 244, 500, 1012, 2036, 4084, 6132, 8180, 10228, 12276, 14324, 16372와 같은 18개의 재할당이 발생합니다.마지막으로 QString에는 16372개의 유니코드 문자가 할당되어 있으며, 그 중 15000개가 사용됩니다.

위의 값이 약간 이상하게 보일 수 있지만 다음은 지침 원칙입니다.

QString은 크기가 20이 될 때까지 한 번에 4개의 문자를 할당합니다.20에서 4084까지, 그것은 매번 두 배의 크기로 발전합니다.더 정확히 말하면, 2의 거듭제곱에서 12를 뺀 다음 거듭제곱으로 진행됩니다. (일부 메모리 할당자는 2의 정확한 거듭제곱을 요청할 때 최악의 성능을 발휘합니다. 왜냐하면 그들은 부기를 위해 블록당 몇 바이트를 사용하기 때문입니다.)4084부터는 2048자(4096바이트) 블록 단위로 진행됩니다.최신 운영 체제는 버퍼를 재할당할 때 전체 데이터를 복사하지 않으며, 물리적 메모리 페이지는 단순하게 재정렬되고 처음 페이지와 마지막 페이지의 데이터만 실제로 복사하면 되기 때문에 이는 타당합니다.

저는 그들이 스마트폰에서 서버 팜에 이르기까지 잘 수행될 수 있는 코드에서 운영 체제 기능을 기대하는 방식을 좋아합니다.그들이 저보다 더 똑똑한 사람들이기 때문에, 저는 그 기능이 모든 최신 OS에서 사용 가능하다고 생각합니다.

번은 사실이었을 수도 있지만, 확실히 더 나은 것은 아닙니다.

필요할 때 필요한 메모리를 할당하고 완료하는 즉시 메모리를 확보합니다.

리소스를 낭비하는 프로그램이 너무 많습니다. 사용자의 프로그램을 리소스 중 하나로 만들지 마십시오.

그것은 다소 관련이 없습니다.

Malloc은 처리할 자체 헤더가 있기 때문에 실제로 사용자가 요청하는 것보다 약간 더 많은 메모리를 할당합니다. 따서최스다는같음습다니과지토와 같은 것일 입니다.4k-12 다릅니다.구현에 따라 다릅니다.

어떤 경우에도 최적화 기술로 필요한 것보다 더 많은 스토리지를 정리해야 할 이유는 없습니다.

프로세서의 워드 크기에 따라 메모리를 할당할 도 있습니다. 2의 오래된 거듭제곱은 불가능합니다.

프로세서에 32비트 워드(4바이트)가 있는 경우 4바이트 단위로 할당합니다.프로세서가 4바이트 경계에서 시작하는 데이터를 선호하기 때문에 2바이트 단위로 할당하는 것은 유용하지 않을 수 있습니다.

반면에, 이것은 미세 최적화일 수 있습니다.대부분의 메모리 할당 라이브러리는 올바른 위치에 정렬되어 있고 조각화의 양이 최소화된 메모리를 반환하도록 설정됩니다.15바이트를 할당하면 라이브러리가 패딩되어 16바이트를 할당할 수 있습니다.일부 메모리 할당자는 할당 크기에 따라 다른 풀을 가집니다.

요약하면 필요한 메모리 양을 할당합니다.할당 라이브러리/관리자가 실제 금액을 처리합니다.이러한 사소한 문제에 대해 걱정하는 것보다 정확성과 견고성에 더 많은 에너지를 쏟으십시오.

아직 알려지지 않은 크기의 데이터를 수용하기 위해 계속해서 증가해야 하는 버퍼를 할당할 때는 2 빼기 1의 거듭제곱부터 시작하여 공간이 부족할 때마다 이전 크기의 두 배 + 1로 재할당합니다.. 할 수 있습니다. 수, ""라는 메시지가 표시됩니다. 이전 크기가 SIZE_MAX일 때만 크기가 오버플로될 수 있습니다. 이때 이미 할당이 실패했을 수 있습니다.2*SIZE_MAX+1 == SIZE_MAX어쨌든.

반대로 2의 거듭제곱을 사용하여 매번 두 배로 늘린 경우 2^31바이트 버퍼를 성공적으로 얻은 다음 크기를 두 배로 늘릴 때 0바이트 버퍼에 다시 할당할 수 있습니다.

어떤 사람들은 power of 2-minus-12가 특정 malloc 구현에 좋다고 언급했듯이, 2 - 12의 power로 시작하여 각 단계에서 2배로 증가하고 12를 추가할 수 있습니다.

반면에 증가할 필요가 없는 작은 버퍼만 할당하는 경우에는 필요한 크기를 정확히 요청하십시오.무엇이 말록에 좋은지 다시 추측하려고 하지 마세요.

이은주어것전의로다니존합적에 전적으로 합니다.libcmalloc(3)힙 청크를 적합하다고 판단되는 순서대로 예약하는 것은 이러한 구현에 달려 있습니다.

질문에 답하자면 - 아니요, "더 나은" 것이 아닙니다(여기서는 "더 나은" 것을 의미합니다...?).작다면, 만약당요사너작면다무가이즈구,malloc(3)내부적으로 더 큰 덩어리를 예약할 테니 정확한 크기만 유지하세요.

오늘날의 메모리 양과 속도로 볼 때 더 이상 관련이 없다고 생각합니다.

또한 메모리를 자주 할당하려면 사용자 지정 메모리 풀링/사전 할당을 고려하는 것이 좋습니다.

항상 테스트가 있습니다...

루프에서 메모리를 할당하는 "샘플" 프로그램을 시도할 수 있습니다.이렇게 하면 컴파일러가 마법처럼 2의 거듭제곱으로 메모리를 할당하는지 확인할 수 있습니다.이 정보를 사용하여 랜덤 크기 블록과 2 크기 블록의 전력이라는 두 가지 전략을 사용하여 동일한 양의 총 메모리를 할당할 수 있습니다.

하지만 많은 양의 메모리에 대해서는 차이가 있을 것으로 예상합니다.

초기 할당을 위해 몇 가지 숫자를 선택해야 하는 확장 가능한 버퍼를 할당하는 경우, 예, 2의 거듭제곱은 선택하기에 좋은 숫자입니다.struct foo에 메모리를 할당해야 하는 경우 malloc(size of(struct foo))만 할당합니다.power-of-2 할당에 대한 권장 사항은 내부 단편화의 비효율성에서 비롯되지만, 멀티프로세서 시스템을 위한 최신 malloc 구현에서는 이 문제가 발생할 정도로 작은 할당에 CPU-local 풀을 사용하기 시작했습니다.이렇게 하면 여러 스레드가 동시에 malloc를 시도하고 조각화로 인해 차단되는 시간이 길어질 때 발생하는 잠금 경합을 방지할 수 있습니다.

필요한 것만 할당하면 데이터 구조가 메모리에 더 촘촘하게 채워지므로 캐시 적중률이 향상되어 내부 단편화보다 성능에 훨씬 큰 영향을 미칩니다.매우 오래된 Malloc 구현과 매우 고급 멀티프로세서 시스템을 사용하는 시나리오가 있습니다. 이 시나리오에서는 할당을 명시적으로 패딩하여 속도를 높일 수 있습니다. 하지만 이러한 경우 리소스를 해당 시스템에서 더 나은 Malloc 구현을 실행하는 데 사용하는 것이 좋습니다.또한 프리패딩을 사용하면 코드 이동성이 떨어지고 사용자나 시스템이 프로그램이나 환경 변수를 사용하여 런타임에 malloc 동작을 선택할 수 없습니다.

섣부른 최적화는 모든 악의 근원입니다.

재할당할 때 malloc() 대신 realloc()를 사용해야 합니다.http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/

항상 2의 거듭제곱을 사용합니까?프로그램이 수행하는 작업에 따라 다릅니다.전체 데이터 구조가 2의 거듭제곱으로 증가할 때 재처리해야 한다면, 당연한 일입니다.그렇지 않으면 필요한 것만 할당하고 메모리를 독차지하지 마십시오.

언급URL : https://stackoverflow.com/questions/3190146/is-it-better-to-allocate-memory-in-the-power-of-two

반응형