skip to content
==> tests/occupancy.c <==
1/* backend.rs's co_residency test, one for one. */
2#include "mesh/check.h"
3#include "mesh/occupancy.h"
4#include "mesh/text.h"
5
6#include <stdlib.h>
7#include <string.h>
8
9static mesh_occ_kernel small[] = {{1, 16}, {1, 16}, {4, 16}, {1, 12}, {2, 16}, {4, 16}};
10
11static char *with(const mesh_occ_kernel *extra, size_t ne, uint32_t sms, uint32_t bps) {
12    mesh_occ_kernel k[16];
13    memcpy(k, small, sizeof small);
14    memcpy(k + 6, extra, ne * sizeof *extra);
15    char *err = NULL;
16    return mesh_co_resident(k, 6 + ne, sms, bps, &err) ? NULL : err;
17}
18
19static bool err_has(char *e, const char *needle) {
20    bool ok = e && strstr(e, needle);
21    if (!ok) fprintf(stderr, "error: %s\n", e ? e : "(none)");
22    free(e);
23    return ok;
24}
25
26int main(void) {
27    /* The RTX 3060 (28 SMs, 16 blocks/SM): kcheck's set and 512-thread x 128-register nodes. */
28    CHECK_U(mesh_occ_room(small, 6, 1, 32, 28, 16), 15);
29    CHECK(with((mesh_occ_kernel[]){{15, 1}}, 1, 28, 16) == NULL);
30    CHECK(err_has(with((mesh_occ_kernel[]){{16, 1}}, 1, 28, 16), "16 node(s) that each need a whole SM"));
31    /* A GB10 (48 SMs, 24/SM): 32 whole-SM pathtrace nodes beside them. */
32    CHECK_U(mesh_occ_room(small, 6, 1, 32, 48, 24), 32);
33    /* Shares: two kernels of half the device each fit, a third does not. */
34    CHECK(mesh_co_resident((mesh_occ_kernel[]){{24, 1}, {24, 1}}, 2, 48, 24, NULL));
35    CHECK(!mesh_co_resident((mesh_occ_kernel[]){{24, 1}, {24, 1}, {1, 24}}, 3, 48, 24, NULL));
36    CHECK(mesh_co_resident((mesh_occ_kernel[]){{48 * 6, 12}, {48 * 6, 12}}, 2, 48, 24, NULL));
37    char *e = NULL;
38    CHECK(!mesh_co_resident((mesh_occ_kernel[]){{48 * 6, 12}, {48 * 6 + 1, 12}}, 2, 48, 24, &e));
39    CHECK(err_has(e, "100%"));
40    /* Per kernel and the block limit. */
41    e = NULL;
42    CHECK(!mesh_co_resident((mesh_occ_kernel[]){{33, 1}}, 1, 32, 24, &e));
43    CHECK(err_has(e, "allows 1 per SM"));
44    CHECK(!mesh_co_resident((mesh_occ_kernel[]){{0, 0}}, 1, 32, 24, NULL));
45    e = NULL;
46    CHECK(!mesh_co_resident((mesh_occ_kernel[]){{17, 32}, {16, 32}}, 2, 1, 32, &e));
47    CHECK(err_has(e, "resident blocks"));
48    /* The exact messages. */
49    e = NULL;
50    mesh_co_resident((mesh_occ_kernel[]){{48 * 6, 12}, {48 * 6 + 1, 12}}, 2, 48, 24, &e);
51    CHECK_S(e, "the loaded kernels would need 100% of the SMs' resident capacity");
52    free(e);
53    e = NULL;
54    mesh_co_resident((mesh_occ_kernel[]){{33, 1}}, 1, 32, 24, &e);
55    CHECK_S(e, "33 blocks; its occupancy allows 1 per SM x 32 SMs");
56    free(e);
57    return mesh_check_done();
58}