cs205-lecture-examples

Example codes used during Harvard CS205 lectures
git clone https://git.0xfab.ch/cs205-lecture-examples.git
Log | Files | Refs | README | LICENSE

daxpy.cpp (3751B)


      1 #include "papi.h"
      2 #include <cstdlib>
      3 #include <iostream>
      4 #include <numeric>
      5 #include <vector>
      6 
      7 // Broadwell CPU on cluster, you can get one with
      8 //   salloc -N1 -c32 -t 01:00:00
      9 //
     10 // Model name: Intel(R) Xeon(R) CPU E5-2683 v4 @ 2.10GHz
     11 // L1d cache:  32K
     12 // L1i cache:  32K
     13 // L2 cache:   256K
     14 // L3 cache:   40960K
     15 #define L1_SIZE_KB 32
     16 #define L2_SIZE_KB 256
     17 #define L3_SIZE_KB 40960
     18 
     19 typedef double Real;
     20 
     21 void daxpy(const Real a, const Real *x, Real *y, const int n)
     22 {
     23     // 2n flops
     24     // 3n memory accesses
     25     for (int i = 0; i < n; ++i) {
     26         y[i] = a * x[i] + y[i];
     27     }
     28 }
     29 
     30 int main(int argc, char *argv[])
     31 {
     32     int n = 1000000;
     33     if (argc > 1) {
     34         n = atoi(argv[1]);
     35     }
     36     std::vector<Real> x(n, 1.0);
     37     std::vector<Real> y(n, 0.001);
     38 
     39     // Initialize PAPI
     40     int event_set = PAPI_NULL;
     41     int events[4] = {PAPI_TOT_CYC,
     42                      PAPI_TOT_INS,
     43                      PAPI_LST_INS,
     44                      PAPI_L1_DCM};
     45     long long int counters[4];
     46     PAPI_library_init(PAPI_VER_CURRENT);
     47     PAPI_create_eventset(&event_set);
     48     PAPI_add_events(event_set, events, 4);
     49 
     50     // warm up
     51     daxpy(1.0, x.data(), y.data(), n);
     52 
     53     // start PAPI measurement
     54     PAPI_start(event_set);
     55 
     56     // assuming no overhead to call this timer (will pollute PAPI_TOT_CYC and
     57     // PAPI_TOT_INS slightly, neglected here)
     58     const long long int t0 = PAPI_get_real_nsec();
     59 
     60     // run code to be measured
     61     daxpy(1.0, x.data(), y.data(), n);
     62 
     63     // assuming no overhead to call this timer (will pollute PAPI_TOT_CYC and
     64     // PAPI_TOT_INS slightly, neglected here)
     65     const long long int t1 = PAPI_get_real_nsec();
     66 
     67     // stop PAPI and get counter values
     68     PAPI_stop(event_set, counters);
     69 
     70     // clang-format off
     71     const long long total_cycles = counters[0];       // cpu cycles
     72     const long long total_instructions = counters[1]; // any
     73     const long long total_load_stores = counters[2];  // number of such instructions
     74     const long long total_l1d_misses = counters[3];   // number of access request to cache line
     75     // clang-format on
     76 
     77     const size_t flops = 2 * n;
     78     const size_t mem_ops = 3 * n;
     79     const double twall = (static_cast<double>(t1) - t0) * 1.0e-9; // seconds
     80     const double IPC = static_cast<double>(total_instructions) / total_cycles;
     81     const double OI =
     82         static_cast<double>(flops) / (total_load_stores * sizeof(Real));
     83     const double OI_theory =
     84         static_cast<double>(flops) / (mem_ops * sizeof(Real));
     85     const double float_perf = flops / twall * 1.0e-9; // Gflop/s
     86     const double sum = std::accumulate(y.begin(), y.end(), 0.0);
     87 
     88     std::cout << "Result:                       " << sum << '\n';
     89     std::cout << "Total cycles:                 " << total_cycles << '\n';
     90     std::cout << "Total instructions:           " << total_instructions << '\n';
     91     std::cout << "Instructions per cycle (IPC): " << IPC << '\n';
     92     std::cout << "L1 cache size:                " << L1_SIZE_KB << " KB\n";
     93     std::cout << "L2 cache size:                " << L2_SIZE_KB << " KB\n";
     94     std::cout << "L3 cache size:                " << L3_SIZE_KB << " KB\n";
     95     std::cout << "Total problem size:           " << 2 * n * sizeof(Real) / 1024
     96               << " KB\n";
     97     std::cout << "Total L1 data misses:         " << total_l1d_misses << '\n';
     98     std::cout << "Total load/store:             " << total_load_stores
     99               << " (expected: " << mem_ops << ")\n";
    100     std::cout << "Operational intensity:        " << std::scientific << OI
    101               << " (expected: " << OI_theory << ")\n";
    102     std::cout << "Performance [Gflop/s]:        " << float_perf << '\n';
    103     std::cout << "Wall-time   [micro-seconds]:  " << twall * 1.0e6 << '\n';
    104 
    105     return 0;
    106 }