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
.