TransferSpeed.hpp 3.01 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 *  @file	TransferSpeed.hpp
 *  @brief	Measures the transfer speed via TPC for a given chunk size.
 *  @author	J. Korinth, TU Darmstadt (jk@esa.cs.tu-darmstadt.de)
 **/
#ifndef __TRANSFER_SPEED_HPP__
#define __TRANSFER_SPEED_HPP__

#include <atomic>
#include <thread>
#include <future>
#include <vector>
#include <sstream>
#include <chrono>
#include <cmath>
#include <unistd.h>
#include <ncurses.h>
18
#include <tapasco_api.hpp>
19
20
21

using namespace std;
using namespace std::chrono;
22
using namespace tapasco;
23
24
25
26

/** Measurement class that can measure TPC memory transfer speeds. **/
class TransferSpeed {
public:
27
  TransferSpeed(Tapasco& tapasco) : tapasco(tapasco) {}
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  virtual ~TransferSpeed() {}

  static constexpr long OP_ALLOCFREE = 0;
  static constexpr long OP_COPYFROM  = 1;
  static constexpr long OP_COPYTO    = 2;

  double operator()(size_t const chunk_sz, long const opmask = 3) {
    double const cs = chunk_sz / 1024.0;
    string const ms = maskToString(opmask);
    CumulativeAverage<double> cavg { 0 };
    bool stop = false;
    bytes = 0;
    int x, y;
    getyx(stdscr, y, x);
42
    auto tstart = steady_clock::now();
43
    double b = 0.0;
44
    duration<double> d = steady_clock::now() - tstart;
45
    future<void> f = async(launch::async, [&]() { transfer(stop, chunk_sz, opmask); });
46
    auto c = getch();
47
48
49
50
    do {
      mvprintw(y, x, "Chunk size: %8.2f KiB, Mask: %s, Speed: %8.2f MiB/s",
          cs, ms.c_str(), cavg());
      refresh();
51
      usleep(1000000);
52
53
      b = bytes.load() / (1024.0 * 1024.0);
      d = steady_clock::now() - tstart;
54
55
56
57
      // exit gracefully on ctrl+c
      c = getch();
      if (c == 3) { endwin(); exit(3); }
    } while (c == ERR && (fabs(cavg.update(b / d.count())) > 0.1 || cavg.size() < 30));
58
59
60
61
62
63
64
65
    stop = true;
    f.get();
    move(y+1, 0);
    return cavg();
  }

private:
  void transfer(volatile bool& stop, size_t const chunk_sz, long opmask) {
66
    tapasco_handle_t h;
67
68
    uint8_t *data = new (std::nothrow) uint8_t[chunk_sz];
    if (! data) return;
69
70
71
72
    for (size_t i = 0; i < chunk_sz; ++i)
      data[i] = rand();

    while (! stop) {
73
      if (tapasco.alloc(h, chunk_sz, TAPASCO_DEVICE_ALLOC_FLAGS_NONE) != TAPASCO_SUCCESS)
74
        throw "allocation failed";
75
      if (opmask & OP_COPYTO && tapasco.copy_to(data, h, chunk_sz, TAPASCO_DEVICE_COPY_BLOCKING) != TAPASCO_SUCCESS)
76
        throw "copy_to failed";
77
      if (opmask & OP_COPYFROM && tapasco.copy_from(h, data, chunk_sz, TAPASCO_DEVICE_COPY_BLOCKING) != TAPASCO_SUCCESS)
78
79
80
81
82
        throw "copy_from failed";
      if (opmask & OP_COPYFROM)
        bytes += chunk_sz;
      if (opmask & OP_COPYTO)
        bytes += chunk_sz;
83
      tapasco.free(h, TAPASCO_DEVICE_ALLOC_FLAGS_NONE);
84
    }
85
    delete[] data;
86
87
88
89
  }

  static const std::string maskToString(long const opmask) {
    stringstream tmp;
90
    tmp << (opmask & OP_COPYFROM ? "r" : " ")
91
92
93
94
95
        << (opmask & OP_COPYTO   ? "w" : " ");
    return tmp.str();
  }

  atomic<uint64_t> bytes { 0 };
96
  Tapasco& tapasco;
97
98
99
100
};

#endif /* __TRANSFER_SPEED_HPP__ */
/* vim: set foldmarker=@{,@} foldlevel=0 foldmethod=marker : */