2017-02-14 3 views
6

Ich möchte diesen einfachen C-Code Benchmark:Probleme Benchmarking einfachen Code mit googlebenchmark

float f(float x[], float y[]) { 
    float p = 0; 
    for (int i = 0; i <64; i++) 
    p += x[i] * y[i]; 
    return p; 
} 

Meine Motivation ist anders Compiler-Flags und auch gcc und Klirren, um zu sehen, welchen Unterschied es macht, um zu versuchen.

Ich fand diese test framework und habe versucht, es zum Laufen zu bringen. Obwohl ich zu C++ ganz neu bin, hier ist meine beste Anstrengung:

#include <benchmark.h> 
#include <benchmark_api.h> 

#include <cstdio> 
#include <random> 

std::random_device seed; 
std::mt19937 gen(seed()); 

float f(float* x, float* y) { 
    float p = 0; 
    for (int i = 0; i <64; i++) { 
    p += x[i] * y[i]; 
    } 
    return p; 
} 

void f_benchmark(benchmark::State& state) { 
    while (state.KeepRunning()) { 
    benchmark::DoNotOptimize(f((float*) state.range(0), (float*) state.range(1))); 
    } 
} 

void args(benchmark::internal::Benchmark* b) { 
    std::uniform_real_distribution<float> rand(0, 100); 

    for (int i = 0; i < 10; i++) { 
    float* x = new float[64]; 
    float* y = new float[64]; 

    for (int i = 0; i < 64; i++) { 
     x[i] = rand(gen); 
     y[i] = rand(gen); 

     printf("%f %f\n", x[i], y[i]); 
    } 

    b->Args({(int) x, (int) y}); 
    } 
} 

BENCHMARK(f_benchmark)->Apply(args); 

BENCHMARK_MAIN(); 

es zu kompilieren ich tun:

g ++ -Ofast -Wall -std = C++ 11 test.cpp -Ibenchmark/include/Benchmark/ -Lbenchmark/src/-o Test -lbenchmark -lpthread

Das gibt mir:

test.cpp: In function ‘void f_benchmark(benchmark::State&)’: 
test.cpp:20:54: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 
    benchmark::DoNotOptimize(f((float*) state.range(0), (float*) state.range(1))); 
[...]                    
test.cpp: In function ‘void args(benchmark::internal::Benchmark*)’: 
test.cpp:38:20: error: cast from ‘float*’ to ‘int’ loses precision [-fpermissive] 
    b->Args({(int) x, (int) y}); 
        ^
[...] 

Wie kann ich diese Warnungen loswerden und im Allgemeinen mache ich das richtig?

+0

Warum alle Güsse? Auf einem 64-Bit-Build wäre 'int' 4 Bytes und' float * '8 Bytes, also kann überhaupt nicht konvertiert werden. Ganz zu schweigen von den Aliasing-Regeln der Sprache. –

+0

@BoPersson Sie können Fehler sein (ich bin komplett neu in C++). Welche könnte ich eliminieren? – eleanora

+0

Wenn ich die Umwandlungen zu int los werde, so dass ich "b-> Args ({x, y}) habe;" Wenn ich dann den Code ausführe, erhalte ich "benchmark/src/benchmark_register.cc: 331: Args: Überprüfen Sie' ArgsCnt() == -1 || ArgsCnt() == static_cast (args.size()) 'fehlgeschlagen. Abgebrochen (Kern abgeladen) " – eleanora

Antwort

3

Ihr Code wirft ein float* zu int und zurück zu einem float* - dies kann zu Problemen führen, weil sizeof(int) und sizeof(float*) sind nicht identisch sein garantiert (dh auf x86-64 int ist 32bit, während float* 64bit ist!) . Der Grund, warum Sie auf dieses Problem stoßen, liegt wahrscheinlich daran, dass Args() nur int Argumente unterstützt (sie sollen als Index für eine Familie von Benchmarks verwendet werden, nicht als tatsächliche Funktionsargumente in Ihrer Funktion). Um Parameter eines anderen Typs verwenden Sie könnte:

A. globale Variablen verwenden, zum Speichern der vorher berechneten statistischen Anordnung dh

#include <benchmark.h> 
#include <benchmark_api.h> 

#include <cstdio> 
#include <random> 

std::random_device seed; 
std::mt19937 gen(seed()); 

float x[64*10], y[64*10]; 

float f(float* x, float* y) { 
    float p = 0; 
    for (int i = 0; i <64; i++) { 
    p += x[i] * y[i]; 
    } 
    return p; 
} 

void f_benchmark(benchmark::State& state) { 
    while (state.KeepRunning()) { 
    benchmark::DoNotOptimize(f(&x[state.range(0)*64], &y[state.range(0)*64])); 
    } 
} 

void args(benchmark::internal::Benchmark* b) { 
    std::uniform_real_distribution<float> rand(0, 100); 
    for (int i = 0; i < 64*10; i++) { 
    x[i] = rand(gen); 
    y[i] = rand(gen); 
    } 
    for (int i = 0; i < 10; ++i) 
    b->Arg({ i }); 
} 
BENCHMARK(f_benchmark)->Apply(args); 
BENCHMARK_MAIN(); 

B. die Zufallszahlen im Rahmen der Benchmark berechnen Funktion (wählen Sie diesen Ansatz, wenn Sie wirklich unterschiedliche Zufallswerte für jede Iteration benötigen - das Timing muss entsprechend pausiert/fortgesetzt werden, um die Zeit für die zufällige Generierung/Speicherzuordnung im Benchmark nicht zu berücksichtigen) dh

#include <benchmark.h> 
#include <benchmark_api.h> 
#include <cstdio> 
#include <random> 

std::random_device seed; 
std::mt19937 gen(seed()); 

float f(float* x, float* y) { 
    float p = 0; 
    for (int i = 0; i <64; i++) { 
    p += x[i] * y[i]; 
    } 
    return p; 
} 

void f_benchmark(benchmark::State& state) { 
    state.PauseTiming(); 
    std::uniform_real_distribution<float> rand(0, 100); 
    float* x = new float[64]; 
    float* y = new float[64]; 
    while (state.KeepRunning()) { 
    for (int i = 0; i < 64; i++) { 
     x[i] = rand(gen); 
     y[i] = rand(gen); 
    } 
    state.ResumeTiming(); 
    benchmark::DoNotOptimize(f(x, y)); 
    state.PauseTiming(); 
    } 
    delete[] x; 
    delete[] y; 
} 


BENCHMARK(f_benchmark)->Apply([](benchmark::internal::Benchmark* b){ 
    for (int i = 0; i < 10; ++i) 
    b->Arg({ i }); 
}); 

BENCHMARK_MAIN(); 

Randbemerkung: Auch die über die undichte Speicher sorgen in Ihrer for Schleife - Sie sollten die delete[] Operator einmal für jeden new[] Betreiber nennen.

+0

Vielen Dank dafür. – eleanora