c++ - Perché l'allocazione della memoria dell'heap è molto più veloce dell'allocazione della memoria dello stack?




performance heap-memory (2)

Ho cercato di allocare spazio per 10 ^ 7 interi nella memoria heap e stack per vedere quale è più veloce. Ovviamente l'allocazione nella memoria heap è stata molto più veloce ma non capisco il motivo.

#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;
}

Altre risposte hanno sottolineato che esiste almeno un'inizializzazione "nascosta" nel costruttore di vettori.

Ma il tuo esempio ha un altro problema: forse non misura nemmeno quello che pensi che faccia. Il benchmarking del codice non ottimizzato in C ++ è praticamente insignificante e il codice ottimizzato per il tempismo corretto è difficile.

Diamo un'occhiata al tuo esempio (modificato per la leggibilità) compilato da Clang con livello di ottimizzazione -O3 : link 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
}

compilato per:

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

La prima parte non chiama nemmeno l'operatore nuovo! Il compilatore ha visto il tuo programma e ha capito che non hai mai usato l'array allocato, quindi ha rimosso l'allocazione dall'eseguibile risultante.

Quindi la prima parte del programma non alloca l'array su heap quando compilato con tali impostazioni rendendo le misurazioni prive di significato.

Raccomando di leggere il benchmarking e utilizzare quadri di micro benchmark specifici per effettuare tali test. Dai un'occhiata a Google Benchmark (e QuickBench online) e alla sua documentazione.


Sono solo un principiante, ma lasciami dare ciò che capisco principalmente per mettermi alla prova.

Nel

int *p = new int[1e7];

stai allocando memoria consecutiva per 10 milioni di numeri interi sull'heap.

Nel

vector<int> v(1e7);

si sta allocando nella memoria dello stack per un oggetto vector<int> . Tra i membri di quell'oggetto c'è un puntatore a un int[1e7] , anch'esso allocato. Inoltre, tutti i valori in esso contenuti sono inizializzati con il valore di int() (con 0s). Vedi il costruttore (2) di std::vector .







stack-memory