Skip to content

Instantly share code, notes, and snippets.

@LucHermitte
Last active October 28, 2015 09:10
Show Gist options
  • Save LucHermitte/7f1b8d5dd61c861e6ef9 to your computer and use it in GitHub Desktop.
Save LucHermitte/7f1b8d5dd61c861e6ef9 to your computer and use it in GitHub Desktop.
itk::VariableLengthVector micro benchmark
#include <benchmark/benchmark.h>
#include <algorithm>
#include "itkVariableLengthVector.h"
static void clobber() {
asm volatile("" : : : "memory");
}
static void BM_create_VLV(benchmark::State & state) {
while (state.KeepRunning()) {
itk::VariableLengthVector<double> v(state.range_x());
// benchmark::DoNotOptimize(&v);
benchmark::DoNotOptimize(&v[0]);
}
}
BENCHMARK(BM_create_VLV)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
static void BM_create_VLV_and_fill(benchmark::State & state) {
while (state.KeepRunning()) {
itk::VariableLengthVector<double> v(state.range_x());
benchmark::DoNotOptimize(&v[0]);
v.Fill(0);
clobber();
}
}
BENCHMARK(BM_create_VLV_and_fill)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
static void BM_copy_VLV(benchmark::State & state) {
while (state.KeepRunning()) {
itk::VariableLengthVector<double> v(state.range_x());
benchmark::DoNotOptimize(&v[0]);
v.Fill(0);
clobber();
itk::VariableLengthVector<double> v2 = v;
benchmark::DoNotOptimize(&v2[0]);
}
}
BENCHMARK(BM_copy_VLV)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
// -- assign into empty
static void BM_assign_to_empty_VLV(benchmark::State & state) {
while (state.KeepRunning()) {
itk::VariableLengthVector<double> v(state.range_x());
benchmark::DoNotOptimize(&v[0]);
v.Fill(0);
clobber();
itk::VariableLengthVector<double> v2;
benchmark::DoNotOptimize(&v2);
v2 = v;
benchmark::DoNotOptimize(&v2[0]);
clobber();
}
}
BENCHMARK(BM_assign_to_empty_VLV)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
static void BM_defensive_assign_to_empty_VLV(benchmark::State & state) {
while (state.KeepRunning()) {
itk::VariableLengthVector<double> v(state.range_x());
benchmark::DoNotOptimize(&v[0]);
v.Fill(0);
clobber();
itk::VariableLengthVector<double> v2;
benchmark::DoNotOptimize(&v2);
v2.DefensiveAssign(v);
benchmark::DoNotOptimize(&v2[0]);
clobber();
}
}
BENCHMARK(BM_defensive_assign_to_empty_VLV)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
static void BM_manual_assign_to_empty_VLV(benchmark::State & state) {
while (state.KeepRunning()) {
itk::VariableLengthVector<double> v(state.range_x());
benchmark::DoNotOptimize(&v[0]);
v.Fill(0);
clobber();
itk::VariableLengthVector<double> v2;
benchmark::DoNotOptimize(&v2);
v2.ManualAssign(v);
benchmark::DoNotOptimize(&v2[0]);
clobber();
}
}
BENCHMARK(BM_manual_assign_to_empty_VLV)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
// -- assign into allocated
static void BM_assign_to_allocated_VLV(benchmark::State & state) {
while (state.KeepRunning()) {
itk::VariableLengthVector<double> v(state.range_x());
benchmark::DoNotOptimize(&v[0]);
v.Fill(0);
clobber();
itk::VariableLengthVector<double> v2(state.range_x());
benchmark::DoNotOptimize(&v2);
v2 = v;
benchmark::DoNotOptimize(&v2[0]);
clobber();
}
}
BENCHMARK(BM_assign_to_allocated_VLV)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
static void BM_defensive_assign_to_allocated_VLV(benchmark::State & state) {
while (state.KeepRunning()) {
itk::VariableLengthVector<double> v(state.range_x());
benchmark::DoNotOptimize(&v[0]);
v.Fill(0);
clobber();
itk::VariableLengthVector<double> v2(state.range_x());
benchmark::DoNotOptimize(&v2);
v2.DefensiveAssign(v);
benchmark::DoNotOptimize(&v2[0]);
clobber();
}
}
BENCHMARK(BM_defensive_assign_to_allocated_VLV)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
static void BM_manual_assign_to_allocated_VLV(benchmark::State & state) {
while (state.KeepRunning()) {
itk::VariableLengthVector<double> v(state.range_x());
benchmark::DoNotOptimize(&v[0]);
v.Fill(0);
clobber();
itk::VariableLengthVector<double> v2(state.range_x());
benchmark::DoNotOptimize(&v2);
v2.ManualAssign(v);
benchmark::DoNotOptimize(&v2[0]);
clobber();
}
}
BENCHMARK(BM_manual_assign_to_allocated_VLV)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
static void BM_fast_assign_to_allocated_VLV(benchmark::State & state) {
while (state.KeepRunning()) {
itk::VariableLengthVector<double> v(state.range_x());
benchmark::DoNotOptimize(&v[0]);
v.Fill(0);
clobber();
itk::VariableLengthVector<double> v2(state.range_x());
benchmark::DoNotOptimize(&v2);
v2.FastAssign(v);
benchmark::DoNotOptimize(&v2[0]);
clobber();
}
}
BENCHMARK(BM_fast_assign_to_allocated_VLV)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
// -- assign, allocations not benchmarked
static void BM_assign_alloc_not_benchmarked(benchmark::State & state) {
itk::VariableLengthVector<double> v(state.range_x());
itk::VariableLengthVector<double> v2(state.range_x());
v.Fill(0);
while (state.KeepRunning()) {
v2 = v;
benchmark::DoNotOptimize(&v2[0]);
clobber();
}
}
BENCHMARK(BM_assign_alloc_not_benchmarked)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
static void BM_defensive_assign_alloc_not_benchmarked(benchmark::State & state) {
itk::VariableLengthVector<double> v(state.range_x());
itk::VariableLengthVector<double> v2(state.range_x());
v.Fill(0);
while (state.KeepRunning()) {
v2.DefensiveAssign(v);
benchmark::DoNotOptimize(&v2[0]);
clobber();
}
}
BENCHMARK(BM_defensive_assign_alloc_not_benchmarked)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
static void BM_manual_assign_alloc_not_benchmarked(benchmark::State & state) {
itk::VariableLengthVector<double> v(state.range_x());
itk::VariableLengthVector<double> v2(state.range_x());
v.Fill(0);
while (state.KeepRunning()) {
v2.ManualAssign(v);
benchmark::DoNotOptimize(&v2[0]);
clobber();
}
}
BENCHMARK(BM_manual_assign_alloc_not_benchmarked)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
static void BM_fast_assign_alloc_not_benchmarked(benchmark::State & state) {
itk::VariableLengthVector<double> v(state.range_x());
itk::VariableLengthVector<double> v2(state.range_x());
v.Fill(0);
while (state.KeepRunning()) {
v2.FastAssign(v);
benchmark::DoNotOptimize(&v2[0]);
clobber();
}
}
BENCHMARK(BM_fast_assign_alloc_not_benchmarked)->Arg(1)->Arg(4)->Arg(16)->Arg(24);
BENCHMARK_MAIN();
// Vim: let $LDFLAGS='-L/home/lhermitte/local/benchmark/lib -L/home/lhermitte/dev/Optims/install/ITK/reldeb/lib -Wl,-rpath /home/lhermitte/dev/Optims/install/ITK/reldeb/lib'
// Vim: let $LDLIBS='-lbenchmark -lITKCommon-4.9'
// Vim: let $CXXFLAGS='-I/home/lhermitte/local/benchmark/include -I/home/lhermitte/dev/Optims/install/ITK/reldeb/include/ITK-4.9 -O3 -fno-omit-frame-pointer -DNDEBUG'
$ ./bench-copy-VLV
Run on (8 X 1998 MHz CPU s)
2015-10-27 12:23:00
***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incure extra overhead.
Benchmark Time(ns) CPU(ns) Iterations
----------------------------------------------------------------------------
BM_create_VLV/1 48 48 13461538
BM_create_VLV/4 48 48 14462810
BM_create_VLV/16 80 80 8333333
BM_create_VLV/24 80 80 8750000
BM_create_VLV_and_fill/1 53 53 13461538
BM_create_VLV_and_fill/4 54 54 13461538
BM_create_VLV_and_fill/16 89 89 7954545
BM_create_VLV_and_fill/24 90 90 7954545
BM_copy_VLV/1 108 108 6250000
BM_copy_VLV/4 111 112 6481481
BM_copy_VLV/16 162 162 4268293
BM_copy_VLV/24 164 164 4166667
BM_assign_to_empty_VLV/1 112 112 6481481
BM_assign_to_empty_VLV/4 110 110 6250000
BM_assign_to_empty_VLV/16 162 162 4375000
BM_assign_to_empty_VLV/24 165 165 4268293
BM_defensive_assign_to_empty_VLV/1 110 110 6481481
BM_defensive_assign_to_empty_VLV/4 111 111 6481481
BM_defensive_assign_to_empty_VLV/16 162 162 4268293
BM_defensive_assign_to_empty_VLV/24 165 164 4268293
BM_manual_assign_to_empty_VLV/1 109 109 6481481
BM_manual_assign_to_empty_VLV/4 107 107 6481481
BM_manual_assign_to_empty_VLV/16 161 162 4375000
BM_manual_assign_to_empty_VLV/24 164 164 4268293
BM_assign_to_allocated_VLV/1 110 110 6481481
BM_assign_to_allocated_VLV/4 110 110 6250000
BM_assign_to_allocated_VLV/16 164 164 4268293
BM_assign_to_allocated_VLV/24 163 163 4268293
BM_defensive_assign_to_allocated_VLV/1 110 110 6250000
BM_defensive_assign_to_allocated_VLV/4 111 111 6250000
BM_defensive_assign_to_allocated_VLV/16 161 161 4268293
BM_defensive_assign_to_allocated_VLV/24 164 164 4268293
BM_manual_assign_to_allocated_VLV/1 105 106 6730769
BM_manual_assign_to_allocated_VLV/4 110 110 6250000
BM_manual_assign_to_allocated_VLV/16 165 165 4268293
BM_manual_assign_to_allocated_VLV/24 169 169 4166667
BM_fast_assign_to_allocated_VLV/1 108 108 6250000
BM_fast_assign_to_allocated_VLV/4 112 111 6034483
BM_fast_assign_to_allocated_VLV/16 161 161 4375000
BM_fast_assign_to_allocated_VLV/24 163 164 4375000
BM_assign_alloc_not_benchmarked/1 6 6 116666667
BM_assign_alloc_not_benchmarked/4 11 11 64814815
BM_assign_alloc_not_benchmarked/16 16 16 43750000
BM_assign_alloc_not_benchmarked/24 18 18 39772727
BM_defensive_assign_alloc_not_benchmarked/1 7 7 102941176
BM_defensive_assign_alloc_not_benchmarked/4 11 11 64814815
BM_defensive_assign_alloc_not_benchmarked/16 16 16 42682927
BM_defensive_assign_alloc_not_benchmarked/24 18 18 38043478
BM_manual_assign_alloc_not_benchmarked/1 4 4 175000000
BM_manual_assign_alloc_not_benchmarked/4 8 8 83333333
BM_manual_assign_alloc_not_benchmarked/16 11 11 64814815
BM_manual_assign_alloc_not_benchmarked/24 14 14 48611111
BM_fast_assign_alloc_not_benchmarked/1 6 6 109375000
BM_fast_assign_alloc_not_benchmarked/4 10 10 67307692
BM_fast_assign_alloc_not_benchmarked/16 16 16 44871795
BM_fast_assign_alloc_not_benchmarked/24 16 16 42682927
/** Copy-Assignment operator */
template< typename TValue >
VariableLengthVector< TValue > &
VariableLengthVector< TValue >
::operator=(const Self & v)
{
// No self assignment test is done. Indeed:
// - the operator already resists self assignment through a strong exception
// guarantee
// - the test becomes a pessimization as we never write "v = v;".
ElementIdentifier const N = v.Size();
this->SetSize( N, DontShrinkToFit(), DumpOldValues() );
std::copy(&v.m_Data[0], &v.m_Data[N], &this->m_Data[0]);
return *this;
}
template< typename TValue >
VariableLengthVector< TValue > &
VariableLengthVector< TValue >
::DefensiveAssign(const Self & v)
{
// No self assignment test is done. Indeed:
// - the operator already resists self assignment through a strong exception
// guarantee
// - the test becomes a pessimization as we never write "v = v;".
ElementIdentifier const N = v.Size();
this->SetSize( N, DontShrinkToFit(), DumpOldValues() );
if (this->m_Data != 0) {
std::copy(&v.m_Data[0], &v.m_Data[N], &this->m_Data[0]);
}
return *this;
}
template< typename TValue >
VariableLengthVector< TValue > &
VariableLengthVector< TValue >
::ManualAssign(const Self & v)
{
// No self assignment test is done. Indeed:
// - the operator already resists self assignment through a strong exception
// guarantee
// - the test becomes a pessimization as we never write "v = v;".
ElementIdentifier const N = v.Size();
this->SetSize( N, DontShrinkToFit(), DumpOldValues() );
for (ElementIdentifier i = 0; i != N; ++i) {
m_Data[i] = v.m_Data[i];
}
return *this;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment