-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patharray.hpp
More file actions
49 lines (40 loc) · 1.64 KB
/
Copy patharray.hpp
File metadata and controls
49 lines (40 loc) · 1.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#ifndef ARRAY_HPP
#define ARRAY_HPP
#include <cstddef>
#include <cstdint>
#include "types.hpp"
#include "config.hpp"
// What one MATMUL's array stepping produces
struct ArrayRun {
Cycle cycles; // latency from stepping
std::uint64_t pe_cycles; // total busy PE-cycles = useful work
};
// This models when each PE is busy, not what it computes..
// The data for PE(i,j) only arrives after i+j hops through the grid,
// and then the PE does one MAC per cycle for K cycles. So PE(i,j) is busy over
// the window [i+j, i+j+K). The far corner PE(R-1, C-1) thus finishes at cycle
// (R-1)+(C-1)+K, which is K+R+C-2 latency. instead we model that by stepping a
// counter and watching the schedule
inline ArrayRun step_array_os(const Config& c, std::size_t K) {
const std::size_t R = c.rows;
const std::size_t C = c.cols;
Cycle t = 0; // clokc
std::uint64_t pe_cycles = 0; // curr count of busy cycles
const std::size_t last_finish = (R - 1) + (C - 1) + K; // PE(R-1,C-1) is done
while (t < last_finish) {
for (std::size_t i = 0; i < R; ++i) {
for (std::size_t j = 0; j < C; ++j) {
const bool busy = (t >= i + j) && (t < i + j + K);
if (busy) ++pe_cycles;
}
}
++t;
}
return { t, pe_cycles }; // t == K+R+C-2, pe_cycles == R*C*K
}
// a systolic array has same fill and drain skew regardless of what stays behind,
// so tile occupancy is same betwen WS and OS
inline ArrayRun step_array_ws(const Config& c, std::size_t K) {
return step_array_os(c, K);
}
#endif