skip to content
==> src/occupancy.c <==
1/* backend.rs's co_resident and room. */
2#include "mesh/occupancy.h"
3#include "mesh/text.h"
4
5#include <stdlib.h>
6#include <string.h>
7
8bool mesh_co_resident(const mesh_occ_kernel *k, size_t n, uint32_t sms, uint32_t blocks_per_sm, char **err) {
9    uint32_t blocks = 0, whole = 0, small = 0;
10    double share = 0;
11    for (size_t i = 0; i < n; i++) {
12        uint32_t nodes = k[i].nodes, per_sm = k[i].per_sm;
13        if (per_sm == 0 || nodes > per_sm * sms)
14            return mesh_errf(err, "%u blocks; its occupancy allows %u per SM x %u SMs", (unsigned)nodes, (unsigned)per_sm, (unsigned)sms);
15        blocks += nodes;
16        share += (double)nodes / (double)(per_sm * sms);
17        if (per_sm == 1) whole += nodes;
18        else small += nodes;
19    }
20    if (blocks > blocks_per_sm * sms)
21        return mesh_errf(err, "%u resident blocks > %u per SM x %u SMs", (unsigned)blocks, (unsigned)blocks_per_sm, (unsigned)sms);
22    if (share > 1.0 + 1e-9) {
23        /* Rust's {:.0}: round half to even, as printf's %.0f. */
24        return mesh_errf(err, "the loaded kernels would need %.0f%% of the SMs' resident capacity", share * 100.0);
25    }
26    uint32_t spread = small < sms ? small : sms;
27    if (whole > 0 && whole + spread > sms)
28        return mesh_errf(err, "%u node(s) that each need a whole SM, and %u other block(s) that may occupy %u SMs, on %u SMs",
29                         (unsigned)whole, (unsigned)small, (unsigned)spread, (unsigned)sms);
30    return true;
31}
32
33uint32_t mesh_occ_room(const mesh_occ_kernel *others, size_t n, uint32_t per_sm, uint32_t max, uint32_t sms, uint32_t blocks_per_sm) {
34    mesh_occ_kernel *k = mesh_alloc((n + 1) * sizeof *k);
35    if (n) memcpy(k, others, n * sizeof *k);
36    k[n] = (mesh_occ_kernel){0, per_sm};
37    uint32_t got = 0;
38    while (got < max) {
39        k[n].nodes = got + 1;
40        if (!mesh_co_resident(k, n + 1, sms, blocks_per_sm, NULL)) break;
41        got++;
42    }
43    free(k);
44    return got;
45}