Download code/tt_meteor/tt/kernels/maxpool_writer.cpp from changh95/meteor-p150: direct link, hf CLI and curl.
- Browser
- Download file 4.52 kB
-
https://huggingface.co/changh95/meteor-p150/resolve/main/code/tt_meteor/tt/kernels/maxpool_writer.cpp
- Command line
-
hf download hf://changh95/meteor-p150/code/tt_meteor/tt/kernels/maxpool_writer.cpp
-
curl -L -o maxpool_writer.cpp https://huggingface.co/changh95/meteor-p150/resolve/main/code/tt_meteor/tt/kernels/maxpool_writer.cpp
4.52 kB
| // SPDX-License-Identifier: Apache-2.0 | |
| // STEM_POOL writer (meteor-p150 OPT round 3 R3.2, tt/pool.py): the horizontal half of the 3x3 / s2 max pool and the | |
| // output. Per unit (work split as the reader), the WT vertical-max tiles of CB 16 hold one input row of 32 * WT | |
| // columns w (tile tx = w / 32, tile row w % 32) for one channel tile. Output column ox takes max(v[2ox-1], v[2ox], | |
| // v[2ox+1]); column -1 is the zero padding (+0.0; W = 2 * OW, so 2ox+1 always exists). The OWT = WT / 2 output tiles | |
| // are built in a scratch CB (24) on this RISC and written to the TILE fp32 output [1, 1, N*OH*OW, C]. | |
| // Compare: the fp32 bits as int32. The inputs are post-ReLU (>= +0.0, or -0.0), where the int32 order is the float | |
| // order with -0.0 < +0.0 (that of the SFPU min / max swap); fp32 is never rounded here. | |
| // Tile element (row r, column c): face ((r / 16) * 2 + c / 16) * 256 + (r % 16) * 16 + c % 16. | |
| // CT args: [0] NU, [1] NC, [2] GX, [3] WT, [4] CT, [5] OH, then the TensorAccessorArgs of the output. | |
| // Common RT args: [out_addr]. | |
| constexpr uint32_t NU = get_compile_time_arg_val(0); | |
| constexpr uint32_t NC = get_compile_time_arg_val(1); | |
| constexpr uint32_t GX = get_compile_time_arg_val(2); | |
| constexpr uint32_t WT = get_compile_time_arg_val(3); | |
| constexpr uint32_t CT = get_compile_time_arg_val(4); | |
| constexpr uint32_t OH = get_compile_time_arg_val(5); | |
| constexpr auto out_args = TensorAccessorArgs<6>(); | |
| constexpr uint32_t OWT = WT / 2; | |
| constexpr uint32_t TB = 4096; | |
| constexpr uint32_t cb_v = 16, cb_s = 24; | |
| static inline uint32_t row_off(uint32_t r) { return (r >> 4) * 512 + (r & 15) * 16; } // + (c / 16) * 256 + c % 16 | |
| void kernel_main() { | |
| const uint32_t core = get_absolute_logical_y() * GX + get_absolute_logical_x(); | |
| if (core >= NC) { | |
| return; | |
| } | |
| constexpr uint32_t B = NU / NC, E = NU % NC; | |
| const uint32_t u0 = core * B + (core < E ? core : E); | |
| const uint32_t nu = B + (core < E ? 1 : 0); | |
| const auto out = TensorAccessor(out_args, get_common_arg_val<uint32_t>(0), TB); | |
| volatile tt_l1_ptr int32_t* s = reinterpret_cast<volatile tt_l1_ptr int32_t*>(get_write_ptr(cb_s)); | |
| for (uint32_t u = u0; u < u0 + nu; ++u) { | |
| const uint32_t ct = u % CT; | |
| const uint32_t q = u / CT; // n * OH + oy | |
| cb_wait_front(cb_v, WT); | |
| volatile tt_l1_ptr int32_t* v = reinterpret_cast<volatile tt_l1_ptr int32_t*>(get_read_ptr(cb_v)); | |
| noc_async_write_barrier(); // the scratch tiles of the previous unit are out | |
| for (uint32_t ot = 0; ot < OWT; ++ot) { | |
| volatile tt_l1_ptr int32_t* o = s + ot * 1024; | |
| for (uint32_t r = 0; r < 32; ++r) { | |
| const uint32_t w1 = (ot * 32 + r) * 2; // 2 ox | |
| const uint32_t w2 = w1 + 1; | |
| volatile tt_l1_ptr int32_t* p1 = v + (w1 >> 5) * 1024 + row_off(w1 & 31); | |
| volatile tt_l1_ptr int32_t* p2 = v + (w2 >> 5) * 1024 + row_off(w2 & 31); | |
| volatile tt_l1_ptr int32_t* q0 = o + row_off(r); | |
| if (w1 == 0) { // column -1: the +0.0 padding | |
| for (uint32_t f = 0; f < 2; ++f) { | |
| for (uint32_t c = 0; c < 16; ++c) { | |
| int32_t m = p1[f * 256 + c]; | |
| const int32_t b = p2[f * 256 + c]; | |
| m = b > m ? b : m; | |
| q0[f * 256 + c] = m > 0 ? m : 0; | |
| } | |
| } | |
| } else { | |
| const uint32_t w0 = w1 - 1; | |
| volatile tt_l1_ptr int32_t* p0 = v + (w0 >> 5) * 1024 + row_off(w0 & 31); | |
| for (uint32_t f = 0; f < 2; ++f) { | |
| for (uint32_t c = 0; c < 16; ++c) { | |
| int32_t m = p0[f * 256 + c]; | |
| const int32_t a = p1[f * 256 + c]; | |
| const int32_t b = p2[f * 256 + c]; | |
| m = a > m ? a : m; | |
| q0[f * 256 + c] = b > m ? b : m; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| cb_pop_front(cb_v, WT); | |
| const uint32_t base = (q * OWT) * CT + ct; | |
| for (uint32_t ot = 0; ot < OWT; ++ot) { | |
| noc_async_write(reinterpret_cast<uint32_t>(s + ot * 1024), out.get_noc_addr(base + ot * CT), TB); | |
| } | |
| } | |
| noc_async_write_barrier(); | |
| } | |