Benchmarks

Ziele:

Beispiel aus der Vorlesung

Wie in der Vorlesung gezeigt, wird in folgendem Programm die Walltime verglichen, die benötigt wird, um Matrizen die zeilen- oder spaltenweise im Speicher liegen zu initalisieren.

Weitere Details:

#include <stdio.h>
#include <stdlib.h>
#include <sys/times.h>
#include <unistd.h>
#include <math.h>


#ifndef MINDIM_M
#define MINDIM_M    1000
#endif

#ifndef MINDIM_N
#define MINDIM_N    1000
#endif

#ifndef MINDIM_K
#define MINDIM_K    1000
#endif

#ifndef MAXDIM_M
#define MAXDIM_M    5000
#endif

#ifndef MAXDIM_N
#define MAXDIM_N    5000
#endif

#ifndef MAXDIM_K
#define MAXDIM_K    5000
#endif

#ifndef INC_M
#define INC_M   100
#endif

#ifndef INC_N
#define INC_N   100
#endif

#ifndef INC_K
#define INC_K   100
#endif

#ifndef MIN_T
#define MIN_T   1
#endif

double buffer[MAXDIM_M*MAXDIM_N];
double buffer1[MAXDIM_M*MAXDIM_N];
double buffer2[MAXDIM_M*MAXDIM_N];

double
walltime()
{
   struct tms    ts;
   static double ClockTick=0.0;

   if (ClockTick==0.0) {
        ClockTick = 1.0 / ((double) sysconf(_SC_CLK_TCK));
   }
   return ((double) times(&ts)) * ClockTick;
}

void
gecopy(long m, long n, const double *A, long incRowA, long incColA,
       double *B, long incRowB, long incColB)
{
    long i, j;

    for (i=0; i<m; ++i) {
        for (j=0; j<n; ++j) {
            B[i*incRowB+j*incColB] = A[i*incRowA+j*incColA];
        }
    }
}

double
asumDiff(long m, long n, const double *A, long incRowA, long incColA,
         const double *B, long incRowB, long incColB)
{
    double diff = 0;
    long   i, j;

    for (i=0; i<m; ++i) {
        for (j=0; j<n; ++j) {
            diff += fabs(B[i*incRowB+j*incColB] - A[i*incRowA+j*incColA]);
        }
    }
    return diff;
}


//------------------------------------------------------------------------------

void
initMatrix(long m, long n, double *A, long incRowA, long incColA)
{
    long i, j;

    for (j=0; j<n; ++j) {
        for (i=0; i<m; ++i) {
            A[i*incRowA+j*incColA] = j*n+i+1;
        }
    }
}

void
printMatrix(long m, long n, const double *A, long incRowA, long incColA)
{
    long i, j;

    for (i=0; i<m; ++i) {
        printf("   ");
        for (j=0; j<n; ++j) {
            printf("%4.1lf ", A[i*incRowA+j*incColA]);
        }
        printf("\n");
    }
    printf("\n");
}

int
main()
{
    long    m, n, runs;
    double  t0, t1, t2, diff;

    printf("#  M    N     t1 (colMajor)  t2 (rowMajor)      t2/t1        diff\n");
    printf("#================================================================\n");

    for (m=MINDIM_M, n=MINDIM_N; m<=MAXDIM_M && n<MAXDIM_N; m+=INC_M, n+=INC_N) {

        printf("%4ld %4ld ", m, n);

        runs = 0;
        t1   = 0;
        do {
            t0 = walltime();
            initMatrix(m, n, buffer, 1, m);
            t1 += walltime() - t0;
            ++runs;
        } while (t1<MIN_T);
        t1 /= runs;
        gecopy(m, n, buffer, 1, m, buffer1, 1, m);

        printf(" %12.2lf", t1);

        runs = 0;
        t2 = 0;
        do {
            t0 = walltime();
            initMatrix(m, n, buffer, n, 1);
            t2 += walltime() - t0;
            ++runs;
        } while (t2<MIN_T);
        t2 /= runs;
        gecopy(m, n, buffer, n, 1, buffer2, n, 1);

        diff = asumDiff(m, n, buffer1, 1, m, buffer2, n, 1);

        printf(" %12.2lf %16.2lf", t2, t2/t1);
        printf(" %11.2le", diff);
        printf("\n");
    }

    return 0;
}

Übersetzen und Ausführen

Hier wurde der Paramter MIN_T beim Übersetzen auf 0 gesetzt, um das Erzeugen dieser Seite zu bescgleunigen.

$shell> gcc -Wall -DMIN_T=0 -o bench_initmatrix bench_initmatrix.c
$shell> ./bench_initmatrix
#  M    N     t1 (colMajor)  t2 (rowMajor)      t2/t1        diff
#================================================================
1000 1000          0.01         0.01             1.00    0.00e+00
1100 1100          0.01         0.02             2.00    0.00e+00
1200 1200          0.01         0.02             2.00    0.00e+00
1300 1300          0.01         0.03             3.00    0.00e+00
1400 1400          0.01         0.03             3.00    0.00e+00
1500 1500          0.01         0.03             3.00    0.00e+00
1600 1600          0.01         0.06             6.00    0.00e+00
1700 1700          0.01         0.05             5.00    0.00e+00
1800 1800          0.02         0.05             2.50    0.00e+00
1900 1900          0.02         0.06             3.00    0.00e+00
2000 2000          0.02         0.07             3.50    0.00e+00
2100 2100          0.02         0.07             3.50    0.00e+00
2200 2200          0.03         0.08             2.67    0.00e+00
2300 2300          0.03         0.09             3.00    0.00e+00
2400 2400          0.04         0.13             3.25    0.00e+00
2500 2500          0.04         0.11             2.75    0.00e+00
2600 2600          0.04         0.12             3.00    0.00e+00
2700 2700          0.04         0.12             3.00    0.00e+00
2800 2800          0.04         0.18             4.50    0.00e+00
2900 2900          0.04         0.14             3.50    0.00e+00
3000 3000          0.05         0.16             3.20    0.00e+00
3100 3100          0.05         0.16             3.20    0.00e+00
3200 3200          0.06         0.24             4.00    0.00e+00
3300 3300          0.06         0.19             3.17    0.00e+00
3400 3400          0.06         0.20             3.33    0.00e+00
3500 3500          0.06         0.21             3.50    0.00e+00
3600 3600          0.08         0.30             3.75    0.00e+00
3700 3700          0.07         0.24             3.43    0.00e+00
3800 3800          0.08         0.26             3.25    0.00e+00
3900 3900          0.09         0.27             3.00    0.00e+00
4000 4000          0.08         0.38             4.75    0.00e+00
4100 4100          0.09         0.30             3.33    0.00e+00
4200 4200          0.10         0.35             3.50    0.00e+00
4300 4300          0.10         0.37             3.70    0.00e+00
4400 4400          0.10         0.46             4.60    0.00e+00
4500 4500          0.11         0.44             4.00    0.00e+00
4600 4600          0.11         0.50             4.55    0.00e+00
4700 4700          0.12         0.49             4.08    0.00e+00
4800 4800          0.12         0.54             4.50    0.00e+00
4900 4900          0.13         0.56             4.31    0.00e+00

Benchmark durchführen

Wir zeigen zunächst an einem Beispiel, wie man generell Plots für Benchmarks macht. Darauf aufbauend sollt ihr eigene Plots zu anderen Charakteristiken (Speedup) und Darstellungsformen (Log-Skalierung) erstellen. Die Aufgabenstellung folgt am Ende des Abschnittes.

Ausgabe in Datei lenken

Da die Ausgabe mit printf alles nach stdout schreibt, können wir diese einfach in eine Datei umlenken:

$shell> ./bench_initmatrix  > report.initmatrix

GNUPlot Skript schreiben

Man kann GNUPlot auch interaktiv bedienen (zeigen wir). Aber genau so wichtig ist es, dass man dafür Skripte schreiben kann, um aus Text-Tabellen Plots erzeugen zu können.

Mit folgendem GNUPlot-Skript werden Plots erstellt, die zeigen wie die Laufzeit vom Speicherformat abhängt:

set terminal svg size 900, 500
set output "bench.initmatrix.svg"
set xlabel "Matrix dim A: M=N"
set title "Matrix-Initialisierung"
set key outside
set pointsize 0.5
plot "report.initmatrix" using 1:3 with linespoints lt 2 lw 3 title "Col-Major", \
     "report.initmatrix" using 1:4 with linespoints lt 3 lw 3 title "Row-Major"

Plots erstellen

$shell> gnuplot plot.initmatrix

Aufgabe