Files
project_6/muh/test/compile_test.cpp
dylanyunlon 57e222b99d [MUH] Fix three-layer disconnect — C++ headers are now the single source of truth
Problems fixed:
  1. gen_patch.py was reading .muh YAML (all nulls) instead of C++ headers.
     Now it parses bi100_* structs directly from tuning_*.cuh via regex,
     extracts constexpr values, and maps them to vllm injection points.
     Verified: 11 patches generated from 6 algorithms.

  2. C++ headers had no build system or tests.
     Added CMakeLists.txt (header-only library target) and compile_test.cpp.
     Verified: g++ -std=c++17 compiles all headers, 17/17 runtime checks pass.
     Also added cuda_compile_test.cu for when nvcc is available.

  3. baseline.muh had a tuning section full of nulls duplicating C++ values.
     Stripped to vllm launch config only. Tuning values live exclusively
     in muh/include/muh/tuning/tuning_*.cuh bi100_* structs.

  4. Fixed constexpr goto in tuning_scan.cuh (C++17 doesn't allow goto in
     constexpr; replaced with early-return + default: break pattern).

Data flow is now:
  tuning_*.cuh (bi100_* constexpr) ──→ gen_patch.py ──→ vllm patches
  baseline.muh (launch config)     ──→ gen_yaml.py  ──→ computility-run.yaml
  compile_test.cpp                 ──→ g++/nvcc     ──→ verify values are real
2026-07-30 14:12:33 +00:00

141 lines
4.3 KiB
C++

// muh/test/compile_test.cpp — Compile-time verification of muh tuning headers
//
// This test does NOT require a GPU. It verifies:
// 1. All headers parse without errors
// 2. All policy_selector functors instantiate and return valid policies
// 3. All bi100_* struct values are non-zero (not forgotten placeholders)
//
// Build: g++ -std=c++17 -I muh/include muh/test/compile_test.cpp -o muh_test
// Run: ./muh_test
#include "muh/muh.cuh"
#include <cassert>
#include <cstdio>
// Helper: verify a value is non-zero (catches forgotten TBD placeholders)
#define CHECK_NONZERO(expr, name) \
do { \
auto _v = (expr); \
if (_v == 0) { \
std::fprintf(stderr, "FAIL: %s == 0 (placeholder not filled)\n", name); \
failures++; \
} else { \
passes++; \
} \
} while(0)
#define CHECK_TRUE(expr, name) \
do { \
if (!(expr)) { \
std::fprintf(stderr, "FAIL: %s\n", name); \
failures++; \
} else { \
passes++; \
} \
} while(0)
int main() {
int passes = 0;
int failures = 0;
auto hw = muh::target_hw;
// --- Verify hardware descriptor ---
CHECK_TRUE(hw.vendor == muh::hardware_capability::vendor_t::iluvatar,
"target_hw.vendor == iluvatar");
CHECK_NONZERO(hw.warp_size, "target_hw.warp_size");
CHECK_NONZERO(hw.max_threads_per_block, "target_hw.max_threads_per_block");
// --- Test reduce policy_selector ---
{
using namespace muh::tuning::reduce;
auto ps = policy_selector{
.accum_t = muh::tuning::type_t::float32,
.operation_t = muh::tuning::op_kind_t::plus,
.offset_size = 4,
.accum_size = 4,
};
auto policy = ps(hw);
CHECK_NONZERO(policy.multi_tile.threads_per_block,
"reduce.float32.threads_per_block");
CHECK_NONZERO(policy.multi_tile.items_per_thread,
"reduce.float32.items_per_thread");
CHECK_NONZERO(policy.multi_tile.vec_size,
"reduce.float32.vec_size");
// Verify known bi100 value matches
CHECK_TRUE(policy.multi_tile.threads_per_block > 0 &&
policy.multi_tile.threads_per_block <= 1024,
"reduce.threads_per_block in [1, 1024]");
}
// --- Test topk policy_selector ---
{
using namespace muh::tuning::topk;
auto ps = policy_selector{.key_size = 2};
auto policy = ps(hw);
CHECK_NONZERO(policy.threads_per_block, "topk.2B.threads_per_block");
CHECK_NONZERO(policy.items_per_thread, "topk.2B.items_per_thread");
CHECK_NONZERO(policy.bits_per_pass, "topk.2B.bits_per_pass");
CHECK_TRUE(policy.bits_per_pass >= 4 && policy.bits_per_pass <= 11,
"topk.bits_per_pass in [4, 11]");
}
// --- Test scan policy_selector ---
{
using namespace muh::tuning::scan;
auto ps = policy_selector{
.input_value_size = 4,
.accum_size = 4,
.offset_size = 4,
.input_type = muh::tuning::type_t::float32,
.accum_type = muh::tuning::type_t::float32,
.operation_t = muh::tuning::op_kind_t::plus,
.is_primitive_accum = true,
};
auto policy = ps(hw);
CHECK_NONZERO(policy.lookback.threads_per_block,
"scan.float32.lookback.threads_per_block");
CHECK_NONZERO(policy.lookback.items_per_thread,
"scan.float32.lookback.items_per_thread");
}
// --- Test transform policy_selector ---
{
using namespace muh::tuning::transform;
auto ps = policy_selector{
.min_elem_size = 2,
.max_elem_size = 2,
.num_inputs = 1,
};
auto policy = ps(hw);
CHECK_NONZERO(policy.bulk.threads_per_block,
"transform.bulk.threads_per_block");
}
// --- Test batch_memcpy policy_selector ---
{
using namespace muh::tuning::batch_memcpy;
auto ps = policy_selector{};
auto policy = ps(hw);
CHECK_NONZERO(policy.threads_per_block,
"batch_memcpy.threads_per_block");
}
// --- Test for_each policy_selector ---
{
using namespace muh::tuning::for_each;
auto ps = policy_selector{};
auto policy = ps(hw);
CHECK_NONZERO(policy.threads_per_block,
"for_each.threads_per_block");
CHECK_NONZERO(policy.items_per_thread,
"for_each.items_per_thread");
}
// --- Report ---
std::printf("\nmuh compile test: %d passed, %d failed\n", passes, failures);
return failures > 0 ? 1 : 0;
}