Files
2026-06-07 13:43:20 -05:00

138 lines
5.7 KiB
Plaintext

//-----------------------------------------------------------------------------------------------
// Copyright (c) 2024 Andrej Karpathy
// Licensed under the MIT License. See the LICENSE file for details.
//
// Modifications Copyright (c) 2025 Hanwen Liu, Hrishi Shah, Kelin Zeng, Charles Pei, and Vijay Daita, ALL RIGHTS RESERVED.
//-----------------------------------------------------------------------------------------------
#include "utils/utils.h"
#include "gpt2.cuh"
int main(int argc, char *argv[]) {
// set up the device
int deviceIdx = 0;
cudaCheck(cudaSetDevice(deviceIdx));
cudaDeviceProp deviceProp;
cudaGetDeviceProperties(&deviceProp, deviceIdx);
// setup cuBLAS and cuBLASLt
cublasCheck(cublasCreate(&cublas_handle));
int enable_tf32 = 0;
// enable_tf32 = deviceProp.major >= 8 ? 1 : 0;
printf("test-gpt2-kernels - TF32 Mode is turned %s\n", enable_tf32 ? "ON." : "OFF.");
cublas_compute_type = enable_tf32 ? CUBLAS_COMPUTE_32F_FAST_TF32 : CUBLAS_COMPUTE_32F;
cublasMath_t cublas_math_mode = enable_tf32 ? CUBLAS_TF32_TENSOR_OP_MATH : CUBLAS_DEFAULT_MATH;
cublasCheck(cublasSetMathMode(cublas_handle, cublas_math_mode));
// build the GPT-2 model from a checkpoint
GPT2 model;
gpt2_build_from_checkpoint(&model, "/work/hdd/bche/Project_GPT/gpt2_124M.bin");
// int C = model.config.channels;
int V = model.config.vocab_size;
int Vp = model.config.padded_vocab_size;
int maxT = model.config.max_seq_len;
// int L = model.config.num_layers;
// load additional information that we will use for debugging and error checking
FILE *state_file = fopenCheck("/work/hdd/bche/Project_GPT/gpt2_inference_verif.bin", "rb");
int state_header[256];
freadCheck(state_header, sizeof(int), 256, state_file);
if (state_header[0] != 20240327) { printf("test-gpt2 - Bad magic state file\n"); exit(EXIT_FAILURE); }
if (state_header[1] != 2) {
fprintf(stderr, "test-gpt2 - Bad version in state file\n");
exit(EXIT_FAILURE);
}
int B = state_header[2]; // batch size, e.g. 4
int T = state_header[3]; // time / sequence length (e.g. 64, up to maxT)
assert(0 <= T && T <= maxT);
printf("test-gpt2 - [State]\n");
printf("Batch Size: %d\n", B);
printf("Sequence Length: %d\n", T);
// inputs and expected outputs, only used for error checking
int* x = (int*)mallocCheck(B * T * sizeof(int));
float* expected_logits = (float*) mallocCheck(B * T * V * sizeof(float));
// read reference information
freadCheck(x, sizeof(int), B*T, state_file);
// freadCheck(y, sizeof(int), B*T, state_file);
fseekCheck(state_file, B*T*sizeof(int), SEEK_CUR);
freadCheck(expected_logits, sizeof(float), B*T*V, state_file);
// freadCheck(expected_loss, sizeof(float), 1, state_file);
// freadCheck(expected_grads_memory, sizeof(float), model.num_parameters, state_file);
fcloseCheck(state_file);
// overall OK signal for the test
int allok = 1;
// First, do target-free forward pass to validate logits
gpt2_forward(&model, x, B, T);
// at this point, target should be equal to expected_logits, let's compare
// copy logits to CPU so we can compare them
float* logits_cpu = (float*)mallocCheck(B * T * Vp * sizeof(float));
cudaCheck(cudaMemcpy(logits_cpu, model.acts.output, B * T * Vp * sizeof(float), cudaMemcpyDeviceToHost));
// compare the output logits from the forward pass
// also careful that we don't access and compare the padded columns of logits
int logits_ok = 1;
double maxerr = 0.0f;
double rmse = 0;
printf("test-gpt2 - Printing 10 Expected vs Actual Logits: \n");
for (int bt = 0; bt < B*T; bt++) {
for (int v = 0; v < V; v++) {
int i = bt * Vp + v; // linearized index
float expected = expected_logits[bt*V + v];
if (i < 10) {
printf("%f, %f\n", expected, logits_cpu[i]);
}
if (isnan(logits_cpu[i])) {
printf("=========================MISMATCH AT INDEX %d,%d: ", bt, v);
printf("%f %f (logit is nan)=========================\n", expected, logits_cpu[i]);
logits_ok = 0;
bt = B*T; // to break out of both loops
break;
}
double abserr = abs(logits_cpu[i] - expected);
double relerr = abs(logits_cpu[i] - expected) / fmaxf(1e-3, abs(expected));
double err = fmin(abserr, relerr);
maxerr = fmaxf(maxerr, err);
rmse += err * err;
if (err > 0.1) {
printf("=========================MISMATCH AT INDEX %d,%d: ", bt, v);
printf("%f %f (err=%f)=========================\n", expected, logits_cpu[i], err);
logits_ok = 0;
bt = B*T; // to break out of both loops
break;
}
}
}
rmse = sqrt(rmse / (B*T*V));
if (rmse > 0.004) {
printf("================ RMSE is too high! (max err %f, RMSE %f) ==================\n", maxerr, rmse);
logits_ok = 0;
}
allok = allok && logits_ok;
if(!logits_ok) {
printf("================ Logits NOT OK! ================\n");
}
else {
printf("---------------- Logits OK! (max err %f, RMSE %f) ----------------\n", maxerr, rmse);
}
// final approval
if (allok) {
printf("_________________________ All tests passed! _________________________\n");
} else {
printf("_________________________ Some tests failed! _________________________\n");
}
// free everything
free(x);
free(expected_logits);
gpt2_free(&model);
cublasCheck(cublasDestroy(cublas_handle));
return 0;
}