簡體   English   中英

為什么分配堆內存要比分配堆棧內存快得多?

[英]Why is allocating heap-memory much faster than allocating stack-memory?

我試圖在堆和堆棧內存中為10 ^ 7個整數分配空間,以查看哪個更快。 顯然,在堆內存中分配要快得多,但我不明白其中的原因。

#include <bits/stdc++.h>
#include <chrono>

using namespace std;
using namespace std::chrono;

int main()
{
  high_resolution_clock::time_point t1 = high_resolution_clock::now();

  int *p = new int[1e7];

  high_resolution_clock::time_point t2 = high_resolution_clock::now();
  auto duration = duration_cast<microseconds>( t2 - t1 ).count();
  cout << duration / 1e6 << "\n"; // 5e-06



  t1 = high_resolution_clock::now();

  vector<int> v(1e7);

  t2 = high_resolution_clock::now();
  duration = duration_cast<microseconds>( t2 - t1 ).count();
  cout << duration / 1e6 << "\n"; // 0.112284

  return 0;
}

new int[1e7]為1e7 int值分配空間,並且不初始化它們。

vector<int> v(1e7); 在堆棧上創建一個vector<int>對象,該對象的構造函數為堆上的1e7 int值分配空間。 還將每個int值初始化為0。

速度的差異是因為初始化。

要比較堆棧分配的速度,您需要在堆棧上分配一個數組:

int data[1e7];

但要注意:這很有可能會失敗,因為堆棧不足以容納那個大陣列。

我只是一個初學者,但是讓我給出我理解的主要是為了測試自己。

int *p = new int[1e7];

你在堆上為1000萬個整數分配連續的內存。

vector<int> v(1e7);

你在堆棧內存上為vector<int>對象分配。 在該對象的成員中,有一個指向堆上的int[1e7]的指針,該指針也被分配。 此外,其中的所有值都使用int() (使用0s)的值初始化。 參見std::vector構造函數(2)

其他答案指出在向量構造函數中至少存在“隱藏”初始化。

但是你的例子有另一個問題:也許它甚至不能衡量你的想法。 在C ++中對未經優化的代碼進行基准測試幾乎毫無意義,並且適當的時序優化代碼很難實現。

讓我們來看看Clang編譯的你的(可讀性修改)示例-O3優化級別: godbolt鏈接

double test1() {
  high_resolution_clock::time_point t1 = high_resolution_clock::now();

  int *p = new int[1e7];

  high_resolution_clock::time_point t2 = high_resolution_clock::now();
  auto duration = duration_cast<microseconds>( t2 - t1 ).count();
  return duration / 1e6; // 5e-06
}

編譯為:

test1():                              # @test1()
        push    rbx
        call    std::chrono::_V2::system_clock::now()
        mov     rbx, rax
        call    std::chrono::_V2::system_clock::now()
        sub     rax, rbx
        movabs  rcx, 2361183241434822607
        imul    rcx
        mov     rax, rdx
        shr     rax, 63
        sar     rdx, 7
        add     rdx, rax
        cvtsi2sd        xmm0, rdx
        divsd   xmm0, qword ptr [rip + .LCPI0_0]
        pop     rbx
        ret
.LCPI1_0:
        .quad   4696837146684686336     # double 1.0E+6

第一部分甚至不叫操作員新! 編譯器通過您的程序看到並意識到您從未使用過已分配的數組,因此它從生成的可執

因此,當使用這樣的設置進行編譯時,程序的第一部分根本不會在堆上分配數組,從而使測量毫無意義。

我建議閱讀有關基准測試的內容,並使用專門的微基准框架來進行此類測試。 看一下Google Benchmark (和在線QuickBench )及其文檔。

我想指出堆棧分配在運行時完全沒有時間; 所有的工作都是由編譯器完成的。 無論優化如何,這種比較都毫無意義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM