Reputation: 23
I have wrote two functions to compare the time cost of std::vector and dynamic allocated array
#include <iostream>
#include <vector>
#include <chrono>
void A() {
auto t1 = std::chrono::high_resolution_clock::now();
std::vector<float> data(5000000);
auto t2 = std::chrono::high_resolution_clock::now();
float *p = data.data();
for (int i = 0; i < 5000000; ++i) {
p[i] = 0.0f;
}
auto t3 = std::chrono::high_resolution_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count() << " us\n";
std::cout << std::chrono::duration_cast<std::chrono::microseconds>(t3 - t2).count() << " us\n";
}
void B() {
auto t1 = std::chrono::high_resolution_clock::now();
auto* data = new float [5000000];
auto t2 = std::chrono::high_resolution_clock::now();
float *ptr = data;
for (int i = 0; i < 5000000; ++i) {
ptr[i] = 0.0f;
}
auto t3 = std::chrono::high_resolution_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count() << " us\n";
std::cout << std::chrono::duration_cast<std::chrono::microseconds>(t3 - t2).count() << " us\n";
}
int main(int argc, char** argv) {
A();
B();
return 0;
}
A() cost about 6000 us to initialize the vector, then 1400 us to fill zeros.
B() cost less than 10 us to allocate memory, then 5800 us to fill zeros.
Why their time costs have such a large difference?
compiler: g++=9.3.0
flags: -O3 -DNDEBUG
Upvotes: 2
Views: 213
Reputation: 1599
QuickBench is a nice tool to compare different ways doing the same thing. https://quick-bench.com/q/p4ThYlVCa7VbO6vy6LEVVZ_0CVs
Your array example leaves a huge memory leak and QuickBench gives an error because of that.
The code I used (added two more variants):
static void Vector(benchmark::State& state) {
// Code inside this loop is measured repeatedly
for (auto _ : state) {
std::vector<float> data(500000);
float *p = data.data();
for (int i = 0; i < 500000; ++i) {
p[i] = 0.0f;
}
// Make sure the variable is not optimized away by compiler
benchmark::DoNotOptimize(data);
}
}
// Register the function as a benchmark
BENCHMARK(Vector);
static void VectorPushBack(benchmark::State& state) {
for (auto _ : state) {
std::vector<float> data;
for (int i = 0; i < 500000; ++i) {
data.push_back(0.0f);
}
benchmark::DoNotOptimize(data);
}
}
BENCHMARK(VectorPushBack);
static void VectorInit(benchmark::State& state) {
for (auto _ : state) {
std::vector<float> data(500000, 0.0f);
benchmark::DoNotOptimize(data);
}
}
BENCHMARK(VectorInit);
static void Array(benchmark::State& state) {
for (auto _ : state) {
auto* data = new float [500000];
float *ptr = data;
for (int i = 0; i < 500000; ++i) {
ptr[i] = 0.0f;
}
benchmark::DoNotOptimize(data);
delete[] data;
}
}
BENCHMARK(Array);
static void ArrayInit(benchmark::State& state) {
for (auto _ : state) {
auto* data = new float [500000]();
benchmark::DoNotOptimize(data);
delete[] data;
}
}
BENCHMARK(ArrayInit);
static void ArrayMemoryLeak(benchmark::State& state) {
for (auto _ : state) {
auto* data = new float [500000];
float *ptr = data;
for (int i = 0; i < 500000; ++i) {
ptr[i] = 0.0f;
}
benchmark::DoNotOptimize(data);
}
}
//BENCHMARK(ArrayMemoryLeak);
All variants but the push_back
one are almost the same in runtime. But the vector is much safer. It's very easy to forget to free the memory (as you demonstrated yourself).
EDIT: Fixed the mistake in the push_back
variant. Thanks to t.niese
and Scheff's Cat
for pointing it out and fixing it.
Upvotes: 4
Reputation: 14875
First, note that the std::vector<float>
constructor already zeros the vector.
There are many plausible system-level explanations for the behavior you observe:
One very plausible is caching: When you allocate the array using new, the memory referenced by the returned pointer is not in the cache. When you create a vector, the constructor will zero the allocated memory area under the hood thereby bringing the memory to the cache. Subsequent zeroing will hit in the cache thus.
Other reasons might include compiler optimizations. A compiler might realize that your zeroing is unneccesary with std::vector. Given the figures you obtained I would discount this here though.
Upvotes: 4