==> 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}