File size: 3,544 Bytes
8be8908 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | /* Include the header under test first: it must be self-contained. */
#include "ggml-gpu-offload-integration.h"
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
static int failures;
static int stub_calls;
static int stub_return_code;
static int captured_m;
static int captured_n;
static int captured_k;
int gpu_local_matmul_f32(const float *A, const float *B, float *C, int M, int N, int K)
{
(void)A;
(void)B;
(void)C;
stub_calls++;
captured_m = M;
captured_n = N;
captured_k = K;
return stub_return_code;
}
static void check(bool condition)
{
if (!condition) {
failures++;
}
}
static void reset_stub(int return_code)
{
stub_calls = 0;
stub_return_code = return_code;
captured_m = 0;
captured_n = 0;
captured_k = 0;
}
static void test_should_try_gpu_offload_boundaries(void)
{
check(!should_try_gpu_offload(511, 511, 511));
check(should_try_gpu_offload(512, 1, 1));
check(should_try_gpu_offload(1, 512, 1));
check(should_try_gpu_offload(1, 1, 512));
check(should_try_gpu_offload(2048, 4, 4));
}
static void test_small_matmul_never_calls_gpu(void)
{
float A[1] = {1.0f};
float B[1] = {2.0f};
float C[1] = {0.0f};
reset_stub(0);
check(!try_gpu_offload_matmul(A, B, C, 8, 16, 32));
check(stub_calls == 0);
}
static void test_large_matmul_reports_gpu_success(void)
{
float A[1] = {1.0f};
float B[1] = {2.0f};
float C[1] = {0.0f};
reset_stub(0);
check(try_gpu_offload_matmul(A, B, C, 512, 16, 32));
check(stub_calls == 1);
check(captured_m == 512);
check(captured_n == 16);
check(captured_k == 32);
}
static void test_large_matmul_falls_back_on_gpu_failure(void)
{
float A[1] = {1.0f};
float B[1] = {2.0f};
float C[1] = {0.0f};
reset_stub(-1);
check(!try_gpu_offload_matmul(A, B, C, 64, 64, 1024));
check(stub_calls == 1);
check(captured_m == 64);
check(captured_n == 64);
check(captured_k == 1024);
}
static void test_oversized_dims_are_not_truncated(void)
{
float A[1] = {1.0f};
float B[1] = {2.0f};
float C[1] = {0.0f};
/* (int)((int64_t)INT_MAX + 1) wraps; the GPU must never see it. */
reset_stub(0);
check(!try_gpu_offload_matmul(A, B, C, (int64_t)INT_MAX + 1, 16, 32));
check(stub_calls == 0);
/* 2^32 + 1024 would truncate to a plausible-looking 1024. */
reset_stub(0);
check(!try_gpu_offload_matmul(A, B, C, 1024, ((int64_t)1 << 32) + 1024, 32));
check(stub_calls == 0);
reset_stub(0);
check(!try_gpu_offload_matmul(A, B, C, 1024, 16, (int64_t)INT_MAX + 7));
check(stub_calls == 0);
/* Largest representable dimension is still offloaded, unmodified. */
reset_stub(0);
check(try_gpu_offload_matmul(A, B, C, INT_MAX, 1, 1));
check(stub_calls == 1);
check(captured_m == INT_MAX);
}
static void test_nonpositive_dims_are_rejected(void)
{
float A[1] = {1.0f};
float B[1] = {2.0f};
float C[1] = {0.0f};
reset_stub(0);
check(!try_gpu_offload_matmul(A, B, C, 1024, 0, 32));
check(stub_calls == 0);
reset_stub(0);
check(!try_gpu_offload_matmul(A, B, C, 1024, 16, -5));
check(stub_calls == 0);
}
int main(void)
{
test_should_try_gpu_offload_boundaries();
test_small_matmul_never_calls_gpu();
test_large_matmul_reports_gpu_success();
test_large_matmul_falls_back_on_gpu_failure();
test_oversized_dims_are_not_truncated();
test_nonpositive_dims_are_rejected();
return failures == 0 ? 0 : 1;
}
|