2024-04-10 18:15:55 +00:00
|
|
|
#define TESTING
|
|
|
|
|
#include "train_gpt2.cu"
|
|
|
|
|
|
|
|
|
|
// poor man's tensor checker
|
2024-04-23 05:00:47 +01:00
|
|
|
int check_tensor(float *a, float *b, int n, const char* label, float threshold=1e-0) {
|
2024-04-27 16:04:55 +00:00
|
|
|
// a is the calculated tensor, b is the reference tensor
|
2024-04-27 15:49:54 +00:00
|
|
|
int print_upto = 10;
|
2024-04-10 18:15:55 +00:00
|
|
|
int ok = 1;
|
2024-04-27 00:54:06 +00:00
|
|
|
float max_diff = 0.0f;
|
2024-04-27 16:04:55 +00:00
|
|
|
float max_rel_error = 0.0f;
|
2024-05-18 13:27:35 +03:00
|
|
|
float max_to_threshold = 0.f;
|
2024-04-27 16:04:55 +00:00
|
|
|
float max_a = 0.0f;
|
|
|
|
|
float max_b = 0.0f;
|
2024-05-18 13:27:35 +03:00
|
|
|
float epsilon = 0.079; // BF16 epsilon value
|
2024-05-18 18:34:24 +00:00
|
|
|
printf("---\n");
|
|
|
|
|
printf("checking tensor: %s\n", label);
|
2024-04-10 18:15:55 +00:00
|
|
|
for (int i = 0; i < n; i++) {
|
2024-05-18 13:27:35 +03:00
|
|
|
float t_eff = threshold + fabs(b[i]) * epsilon;
|
2024-04-27 00:54:06 +00:00
|
|
|
float diff = fabsf(a[i] - b[i]);
|
2024-05-18 13:27:35 +03:00
|
|
|
max_to_threshold = max(max_to_threshold, diff / t_eff);
|
2024-04-27 16:04:55 +00:00
|
|
|
if (diff > max_diff) {
|
|
|
|
|
max_diff = diff;
|
|
|
|
|
float denom = fabsf(b[i]);
|
|
|
|
|
max_rel_error = (denom == 0.0f) ? 0.0f : diff / denom;
|
|
|
|
|
max_a = a[i];
|
|
|
|
|
max_b = b[i];
|
|
|
|
|
}
|
2024-05-18 13:27:35 +03:00
|
|
|
if (diff > t_eff) {
|
2024-04-10 18:15:55 +00:00
|
|
|
ok = 0;
|
|
|
|
|
}
|
2024-05-18 18:34:24 +00:00
|
|
|
// print the first few elements so we can visually assess the "proof" of the comparison
|
|
|
|
|
if (i < print_upto) {
|
|
|
|
|
printf(diff <= t_eff ? "OK " : "NOT OK ");
|
|
|
|
|
printf("%f %f\n", a[i], b[i]);
|
|
|
|
|
}
|
2024-04-10 18:15:55 +00:00
|
|
|
}
|
|
|
|
|
// print the final result
|
|
|
|
|
if (ok) {
|
2024-05-18 13:27:35 +03:00
|
|
|
printf("TENSOR OK, max diff: %.3e, with rel error: %.3e (calculated=%10f, ref=%10f), %.2f%% of maximum error\n",
|
|
|
|
|
max_diff, max_rel_error, max_a, max_b, max_to_threshold*100);
|
2024-04-10 18:15:55 +00:00
|
|
|
} else {
|
2024-05-18 13:27:35 +03:00
|
|
|
printf("TENSOR NOT OK, max diff: %.3e, with rel error: %.3e (calculated=%10f, ref=%10f), %.2f%% of maximum error\n",
|
|
|
|
|
max_diff, max_rel_error, max_a, max_b, max_to_threshold*100);
|
|
|
|
|
}
|
2024-04-10 18:15:55 +00:00
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-27 15:27:05 +00:00
|
|
|
// the same tensors as in the train file, but in float, which are used as reference
|
|
|
|
|
typedef struct {
|
padded vocab change. touched a lot of code. very stressful and error prone, but i think it is done. had to bump versions on all .bin files, invalidating the previous files. re-run the python training script to re-export the new version files. let's not do too much of things like this in the future lol. actually, fun fact i had a chance to do the padded vocab really really early in the history of llm.c development, and chose not do it, thinking i'll just do it later. i should have done it. such is life, you make mistakes, you accumulate scar tissue, and you learn, and you become better, faster, stronger. this is the mindset one must have to lead a happy and fulfilling life. it's not important that you are perfect at any point in time, it's only important that you keep improving, every day.
2024-04-28 18:47:03 +00:00
|
|
|
float* wte; // (Vp, C)
|
2024-04-27 15:27:05 +00:00
|
|
|
float* wpe; // (maxT, C)
|
2024-04-28 00:02:51 +00:00
|
|
|
float* ln1w; // (L, C)
|
|
|
|
|
float* ln1b; // (L, C)
|
2024-04-27 15:27:05 +00:00
|
|
|
float* qkvw; // (L, 3*C, C)
|
|
|
|
|
float* qkvb; // (L, 3*C)
|
|
|
|
|
float* attprojw; // (L, C, C)
|
|
|
|
|
float* attprojb; // (L, C)
|
2024-04-28 00:02:51 +00:00
|
|
|
float* ln2w; // (L, C)
|
|
|
|
|
float* ln2b; // (L, C)
|
2024-04-27 15:27:05 +00:00
|
|
|
float* fcw; // (L, 4*C, C)
|
|
|
|
|
float* fcb; // (L, 4*C)
|
|
|
|
|
float* fcprojw; // (L, C, 4*C)
|
|
|
|
|
float* fcprojb; // (L, C)
|
|
|
|
|
float* lnfw; // (C)
|
|
|
|
|
float* lnfb; // (C)
|
|
|
|
|
} FloatParameterTensors;
|
|
|
|
|
static_assert(sizeof(FloatParameterTensors) == NUM_PARAMETER_TENSORS * sizeof(void*), "Inconsistent sizes!");
|
|
|
|
|
|
|
|
|
|
// malloc_and_point, but in float and on CPU, because we use this data to check correctness on CPU
|
|
|
|
|
float* float_cpu_malloc_and_point_parameters(FloatParameterTensors* params, size_t* param_sizes) {
|
2024-04-28 00:02:51 +00:00
|
|
|
// calculate the total number of parameters
|
2024-04-27 15:27:05 +00:00
|
|
|
size_t num_parameters = 0;
|
|
|
|
|
for (int i = 0; i < NUM_PARAMETER_TENSORS; i++) {
|
|
|
|
|
num_parameters += param_sizes[i];
|
|
|
|
|
}
|
2024-04-28 00:02:51 +00:00
|
|
|
// everything is float so number of bytes to allocate is a simple multiplication
|
2024-04-27 15:27:05 +00:00
|
|
|
float* params_memory = (float*)mallocCheck(num_parameters * sizeof(float));
|
|
|
|
|
float** ptrs[] = {
|
2024-04-28 00:02:51 +00:00
|
|
|
¶ms->wte, ¶ms->wpe, ¶ms->ln1w, ¶ms->ln1b, ¶ms->qkvw, ¶ms->qkvb,
|
|
|
|
|
¶ms->attprojw, ¶ms->attprojb, ¶ms->ln2w, ¶ms->ln2b, ¶ms->fcw, ¶ms->fcb,
|
|
|
|
|
¶ms->fcprojw, ¶ms->fcprojb, ¶ms->lnfw, ¶ms->lnfb
|
2024-04-27 15:27:05 +00:00
|
|
|
};
|
|
|
|
|
float* params_memory_iterator = params_memory;
|
|
|
|
|
for (int i = 0; i < NUM_PARAMETER_TENSORS; i++) {
|
|
|
|
|
*(ptrs[i]) = params_memory_iterator;
|
|
|
|
|
params_memory_iterator += param_sizes[i];
|
|
|
|
|
}
|
|
|
|
|
return params_memory;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-10 18:15:55 +00:00
|
|
|
int main(int argc, char *argv[]) {
|
2024-05-16 11:17:55 +03:00
|
|
|
multi_gpu_config = multi_gpu_config_init(&argc, &argv);
|
2024-05-05 15:05:59 +01:00
|
|
|
common_start(false, true);
|
2024-04-30 17:00:09 +01:00
|
|
|
|
2024-05-08 20:18:33 +00:00
|
|
|
// set the right paths
|
|
|
|
|
#if defined(ENABLE_BF16)
|
|
|
|
|
const char* load_filename = "gpt2_124M_bf16.bin";
|
|
|
|
|
#else
|
|
|
|
|
const char* load_filename = "gpt2_124M.bin";
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-04-10 18:15:55 +00:00
|
|
|
// build the GPT-2 model from a checkpoint
|
|
|
|
|
GPT2 model;
|
2024-05-08 20:18:33 +00:00
|
|
|
|
2024-04-30 18:38:38 +00:00
|
|
|
gpt2_build_from_checkpoint(&model, load_filename);
|
2024-04-27 00:54:06 +00:00
|
|
|
size_t V = model.config.vocab_size;
|
padded vocab change. touched a lot of code. very stressful and error prone, but i think it is done. had to bump versions on all .bin files, invalidating the previous files. re-run the python training script to re-export the new version files. let's not do too much of things like this in the future lol. actually, fun fact i had a chance to do the padded vocab really really early in the history of llm.c development, and chose not do it, thinking i'll just do it later. i should have done it. such is life, you make mistakes, you accumulate scar tissue, and you learn, and you become better, faster, stronger. this is the mindset one must have to lead a happy and fulfilling life. it's not important that you are perfect at any point in time, it's only important that you keep improving, every day.
2024-04-28 18:47:03 +00:00
|
|
|
size_t Vp = model.config.padded_vocab_size;
|
2024-04-27 00:54:06 +00:00
|
|
|
size_t maxT = model.config.max_seq_len;
|
|
|
|
|
size_t L = model.config.num_layers;
|
|
|
|
|
size_t C = model.config.channels;
|
2024-04-10 18:15:55 +00:00
|
|
|
|
|
|
|
|
// load additional information that we will use for debugging and error checking
|
2024-04-16 20:16:26 +00:00
|
|
|
FILE *state_file = fopenCheck("gpt2_124M_debug_state.bin", "rb");
|
2024-04-10 18:15:55 +00:00
|
|
|
int state_header[256];
|
2024-04-16 20:16:26 +00:00
|
|
|
freadCheck(state_header, sizeof(int), 256, state_file);
|
padded vocab change. touched a lot of code. very stressful and error prone, but i think it is done. had to bump versions on all .bin files, invalidating the previous files. re-run the python training script to re-export the new version files. let's not do too much of things like this in the future lol. actually, fun fact i had a chance to do the padded vocab really really early in the history of llm.c development, and chose not do it, thinking i'll just do it later. i should have done it. such is life, you make mistakes, you accumulate scar tissue, and you learn, and you become better, faster, stronger. this is the mindset one must have to lead a happy and fulfilling life. it's not important that you are perfect at any point in time, it's only important that you keep improving, every day.
2024-04-28 18:47:03 +00:00
|
|
|
if (state_header[0] != 20240327) { fprintf(stderr, "Bad magic state file\n"); exit(EXIT_FAILURE); }
|
|
|
|
|
if (state_header[1] != 2) {
|
|
|
|
|
fprintf(stderr, "Bad version in state file\n");
|
|
|
|
|
fprintf(stderr, "---> HINT: try to re-run `python train_gpt2.py`\n");
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
2024-04-10 18:15:55 +00:00
|
|
|
int B = state_header[2]; // batch size, e.g. 4
|
|
|
|
|
int T = state_header[3]; // time / sequence length (e.g. 64, up to maxT)
|
2024-04-16 20:16:26 +00:00
|
|
|
assert(0 <= T && T <= maxT);
|
2024-04-10 18:15:55 +00:00
|
|
|
printf("[State]\n");
|
|
|
|
|
printf("batch_size: %d\n", B);
|
|
|
|
|
printf("seq_len: %d\n", T);
|
|
|
|
|
|
2024-05-16 11:17:55 +03:00
|
|
|
set_zero_configs(&multi_gpu_config, 0, model.num_parameters);
|
|
|
|
|
|
2024-04-27 15:27:05 +00:00
|
|
|
// read reference information from the file saved from Python/PyTorch side
|
|
|
|
|
// 1) input x and y
|
2024-04-16 20:16:26 +00:00
|
|
|
int* x = (int*)mallocCheck(B * T * sizeof(int));
|
|
|
|
|
int* y = (int*)mallocCheck(B * T * sizeof(int));
|
|
|
|
|
freadCheck(x, sizeof(int), B*T, state_file);
|
|
|
|
|
freadCheck(y, sizeof(int), B*T, state_file);
|
2024-04-27 15:27:05 +00:00
|
|
|
// 2) results of forward pass (logits and loss)
|
|
|
|
|
float* expected_logits = (float*) mallocCheck(B * T * V * sizeof(float));
|
|
|
|
|
float* expected_loss = (float*) mallocCheck(1 * sizeof(float));
|
2024-04-16 20:16:26 +00:00
|
|
|
freadCheck(expected_logits, sizeof(float), B*T*V, state_file);
|
|
|
|
|
freadCheck(expected_loss, sizeof(float), 1, state_file);
|
2024-04-27 15:27:05 +00:00
|
|
|
// 3) results of backward pass (parameter gradients)
|
|
|
|
|
FloatParameterTensors expected_grads; // will be read from file. right now: all in fp32
|
|
|
|
|
float* expected_grads_memory = float_cpu_malloc_and_point_parameters(&expected_grads, model.param_elements);
|
2024-04-16 20:16:26 +00:00
|
|
|
freadCheck(expected_grads_memory, sizeof(float), model.num_parameters, state_file);
|
|
|
|
|
fcloseCheck(state_file);
|
2024-04-10 18:15:55 +00:00
|
|
|
|
2024-04-27 15:27:05 +00:00
|
|
|
// this memory will be used to do one single copy of all (mixed precision) GPU grads to CPU grads
|
|
|
|
|
void* grads_memory_cpu = mallocCheck(model.num_parameters_bytes);
|
|
|
|
|
float* grads_memory_cpu_float = (float*)mallocCheck(model.num_parameters * sizeof(float));
|
|
|
|
|
|
2024-04-10 18:15:55 +00:00
|
|
|
// overall OK signal for the test
|
|
|
|
|
int allok = 1;
|
|
|
|
|
|
2024-04-20 01:20:36 +03:00
|
|
|
// First, do target-free forward pass to validate logits
|
|
|
|
|
gpt2_forward(&model, x, NULL, B, T);
|
|
|
|
|
// at this point, target should be equal to expected_logits, let's compare
|
|
|
|
|
// copy logits to CPU so we can compare them
|
padded vocab change. touched a lot of code. very stressful and error prone, but i think it is done. had to bump versions on all .bin files, invalidating the previous files. re-run the python training script to re-export the new version files. let's not do too much of things like this in the future lol. actually, fun fact i had a chance to do the padded vocab really really early in the history of llm.c development, and chose not do it, thinking i'll just do it later. i should have done it. such is life, you make mistakes, you accumulate scar tissue, and you learn, and you become better, faster, stronger. this is the mindset one must have to lead a happy and fulfilling life. it's not important that you are perfect at any point in time, it's only important that you keep improving, every day.
2024-04-28 18:47:03 +00:00
|
|
|
floatX* logits_cpu_raw = (floatX*)mallocCheck(B * T * Vp * sizeof(floatX));
|
|
|
|
|
float* logits_cpu = (float*)mallocCheck(B * T * Vp * sizeof(float));
|
|
|
|
|
cudaMemcpy(logits_cpu_raw, model.acts.output, B * T * Vp * sizeof(floatX), cudaMemcpyDeviceToHost);
|
|
|
|
|
for (int i = 0; i < B * T * Vp; i++) {
|
2024-04-23 05:00:47 +01:00
|
|
|
logits_cpu[i] = (float)logits_cpu_raw[i];
|
|
|
|
|
}
|
2024-04-22 18:09:18 +01:00
|
|
|
|
2024-04-27 00:54:06 +00:00
|
|
|
// FP16 and lower require very high tolerances unfortunately. TODO look into more
|
2024-04-27 23:17:22 +00:00
|
|
|
float logit_accuracy_threshold = 1e-2f;
|
|
|
|
|
float loss_diff_threshold = 0.05f;
|
2024-04-23 01:39:33 +01:00
|
|
|
#if defined(ENABLE_BF16) || defined(ENABLE_F16)
|
2024-04-30 17:00:09 +01:00
|
|
|
logit_accuracy_threshold = 25.0f; // 15.0f was too low even without cuDNN?! :(
|
2024-04-22 18:09:18 +01:00
|
|
|
#endif
|
|
|
|
|
|
padded vocab change. touched a lot of code. very stressful and error prone, but i think it is done. had to bump versions on all .bin files, invalidating the previous files. re-run the python training script to re-export the new version files. let's not do too much of things like this in the future lol. actually, fun fact i had a chance to do the padded vocab really really early in the history of llm.c development, and chose not do it, thinking i'll just do it later. i should have done it. such is life, you make mistakes, you accumulate scar tissue, and you learn, and you become better, faster, stronger. this is the mindset one must have to lead a happy and fulfilling life. it's not important that you are perfect at any point in time, it's only important that you keep improving, every day.
2024-04-28 18:47:03 +00:00
|
|
|
// 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;
|
2024-04-27 23:17:22 +00:00
|
|
|
float max_diff = 0.0f;
|
padded vocab change. touched a lot of code. very stressful and error prone, but i think it is done. had to bump versions on all .bin files, invalidating the previous files. re-run the python training script to re-export the new version files. let's not do too much of things like this in the future lol. actually, fun fact i had a chance to do the padded vocab really really early in the history of llm.c development, and chose not do it, thinking i'll just do it later. i should have done it. such is life, you make mistakes, you accumulate scar tissue, and you learn, and you become better, faster, stronger. this is the mindset one must have to lead a happy and fulfilling life. it's not important that you are perfect at any point in time, it's only important that you keep improving, every day.
2024-04-28 18:47:03 +00:00
|
|
|
for (int bt = 0; bt < B*T; bt++) {
|
|
|
|
|
for (int v = 0; v < V; v++) {
|
|
|
|
|
int i = bt * Vp + v; // linearized index
|
|
|
|
|
if (i < 10) {
|
|
|
|
|
printf("%f, %f\n", expected_logits[i], logits_cpu[i]);
|
|
|
|
|
}
|
|
|
|
|
float diff = fabsf(expected_logits[bt*V + v] - logits_cpu[i]);
|
|
|
|
|
max_diff = fmaxf(max_diff, diff);
|
|
|
|
|
if (diff >= logit_accuracy_threshold) {
|
|
|
|
|
printf("MISMATCH AT INDEX %d,%d: ", bt, v);
|
|
|
|
|
printf("%f %f\n", expected_logits[bt*V + v], logits_cpu[i]);
|
|
|
|
|
logits_ok = 0;
|
|
|
|
|
bt = B*T; // to break out of both loops
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-04-20 01:20:36 +03:00
|
|
|
}
|
|
|
|
|
}
|
2024-04-27 00:54:06 +00:00
|
|
|
allok = allok && logits_ok;
|
2024-04-20 01:20:36 +03:00
|
|
|
if(!logits_ok) { printf("NOT "); }
|
|
|
|
|
printf("OK (LOGITS)\n");
|
2024-04-27 23:17:22 +00:00
|
|
|
printf("logit max diff: %f\n", max_diff);
|
2024-04-20 01:20:36 +03:00
|
|
|
|
2024-04-10 18:15:55 +00:00
|
|
|
// let's do 10 training iterations, following the pytorch code
|
|
|
|
|
float losses[10];
|
|
|
|
|
for (int step = 0; step < 10; step++) {
|
|
|
|
|
struct timespec start, end;
|
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &start);
|
|
|
|
|
gpt2_forward(&model, x, y, B, T);
|
2024-04-16 02:10:45 +00:00
|
|
|
gpt2_zero_grad(&model);
|
2024-05-21 15:57:07 +01:00
|
|
|
gpt2_backward(&model, x);
|
2024-04-10 18:15:55 +00:00
|
|
|
clock_gettime(CLOCK_MONOTONIC, &end);
|
|
|
|
|
double time_elapsed_s = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
|
|
|
|
|
|
|
|
|
|
if (step == 0) {
|
|
|
|
|
// error checking at step 0 for reference activations
|
|
|
|
|
|
|
|
|
|
// compare the achieved loss
|
2024-04-27 23:17:22 +00:00
|
|
|
if (fabsf(model.mean_loss - *expected_loss) >= loss_diff_threshold) {
|
2024-04-10 18:15:55 +00:00
|
|
|
printf("LOSS MISMATCH: %f %f\n", model.mean_loss, *expected_loss);
|
|
|
|
|
allok = 0;
|
|
|
|
|
} else {
|
|
|
|
|
printf("LOSS OK: %f %f\n", model.mean_loss, *expected_loss);
|
|
|
|
|
}
|
2024-04-16 02:10:45 +00:00
|
|
|
|
2024-04-27 15:27:05 +00:00
|
|
|
// move the (mixed precision) grads from GPU to CPU
|
|
|
|
|
cudaMemcpy(grads_memory_cpu, model.grads_memory, model.num_parameters_bytes, cudaMemcpyDeviceToHost);
|
2024-04-17 04:41:58 +00:00
|
|
|
|
2024-04-27 15:27:05 +00:00
|
|
|
// convert all gradients to float on the CPU
|
|
|
|
|
char* src_iterator = (char*)grads_memory_cpu; // can be lower precision, so we use char*
|
|
|
|
|
float* dst_iterator = (float*)grads_memory_cpu_float; // float*
|
|
|
|
|
float* exp_iterator = expected_grads_memory; // float* of expected gradients from Python
|
2024-04-27 00:54:06 +00:00
|
|
|
float* tensors1[NUM_PARAMETER_TENSORS];
|
|
|
|
|
float* tensors2[NUM_PARAMETER_TENSORS];
|
|
|
|
|
for (int i = 0; i < NUM_PARAMETER_TENSORS; i++) {
|
2024-04-22 18:09:18 +01:00
|
|
|
if (model.param_sizeof[i] == sizeof(float)) {
|
2024-04-27 00:54:06 +00:00
|
|
|
// float tensor => copy over directly
|
2024-04-23 01:39:33 +01:00
|
|
|
memcpy(dst_iterator, src_iterator, model.param_elements[i] * sizeof(float));
|
2024-04-22 18:09:18 +01:00
|
|
|
} else {
|
2024-04-27 00:54:06 +00:00
|
|
|
// low-precision tensor => convert to float
|
2024-04-27 15:27:05 +00:00
|
|
|
assert(model.param_sizeof[i] == sizeof(floatX)); // floatX is the single non-float supported atm
|
2024-04-22 18:09:18 +01:00
|
|
|
for (size_t j = 0; j < model.param_elements[i]; j++) {
|
2024-04-27 15:27:05 +00:00
|
|
|
dst_iterator[j] = ((floatX*)src_iterator)[j]; // convert to float
|
2024-04-22 18:09:18 +01:00
|
|
|
}
|
|
|
|
|
}
|
2024-04-27 15:27:05 +00:00
|
|
|
// for convenience record the position of comparison for reality vs. expectation
|
|
|
|
|
tensors1[i] = dst_iterator; // reality
|
|
|
|
|
tensors2[i] = exp_iterator; // expectation
|
|
|
|
|
// advance the iterators
|
2024-04-23 01:39:33 +01:00
|
|
|
src_iterator += model.param_elements[i] * model.param_sizeof[i];
|
|
|
|
|
dst_iterator += model.param_elements[i];
|
2024-04-27 00:54:06 +00:00
|
|
|
exp_iterator += model.param_elements[i];
|
2024-04-22 18:09:18 +01:00
|
|
|
}
|
2024-04-27 00:54:06 +00:00
|
|
|
|
|
|
|
|
// compare the gradients on the parameters all at once, in fp32
|
2024-04-27 15:49:54 +00:00
|
|
|
// I set the tolerances manually by inspecting the gradient differences for
|
2024-04-28 00:05:03 +00:00
|
|
|
// a few elements of each tensor. bf16 looks ok but not amazing here.
|
|
|
|
|
// It's possible we have bugs lurking, or maybe it is bf16. Not 100% sure.
|
padded vocab change. touched a lot of code. very stressful and error prone, but i think it is done. had to bump versions on all .bin files, invalidating the previous files. re-run the python training script to re-export the new version files. let's not do too much of things like this in the future lol. actually, fun fact i had a chance to do the padded vocab really really early in the history of llm.c development, and chose not do it, thinking i'll just do it later. i should have done it. such is life, you make mistakes, you accumulate scar tissue, and you learn, and you become better, faster, stronger. this is the mindset one must have to lead a happy and fulfilling life. it's not important that you are perfect at any point in time, it's only important that you keep improving, every day.
2024-04-28 18:47:03 +00:00
|
|
|
// Also, if code changes and some of these get tripped, it could be ok if it's not by too much,
|
|
|
|
|
// because our use of stochastic rounding is adding some non-determinism "pepper noise".
|
|
|
|
|
// In that case it's ok to extend the tolerance by a bit, after a manual review.
|
2024-05-18 13:27:35 +03:00
|
|
|
// Also, different GPUs may use different matrix multiplication algorithms, so the
|
|
|
|
|
// actual errors can be hardware specific.
|
2024-05-18 18:34:24 +00:00
|
|
|
allok = allok & check_tensor(tensors1[0], tensors2[0], V * C, "wte", 6e-1f); // hmm a bit high
|
2024-05-18 13:27:35 +03:00
|
|
|
allok = allok & check_tensor(tensors1[1], tensors2[1], maxT * C, "wpe", 4e-3f);
|
|
|
|
|
allok = allok & check_tensor(tensors1[2], tensors2[2], L * 3*C * C, "qkvw", 1e-1); // hmm a bit high
|
|
|
|
|
allok = allok & check_tensor(tensors1[3], tensors2[3], L * 3*C, "qkvb", 3.5e-2f);
|
|
|
|
|
allok = allok & check_tensor(tensors1[4], tensors2[4], L * C * C, "attprojw", 2e-2f);
|
2024-04-27 23:17:22 +00:00
|
|
|
allok = allok & check_tensor(tensors1[5], tensors2[5], L * C, "attprojb", 3e-2f);
|
2024-05-18 13:27:35 +03:00
|
|
|
allok = allok & check_tensor(tensors1[6], tensors2[6], L * 4*C * C, "fcw", 5e-2f); // hmm a bit high
|
|
|
|
|
allok = allok & check_tensor(tensors1[7], tensors2[7], L * 4*C, "fcb", 5e-2f); // hmm a bit high
|
|
|
|
|
allok = allok & check_tensor(tensors1[8], tensors2[8], L * C * 4*C, "fcprojw", 5e-2f); // hmm a bit high
|
|
|
|
|
allok = allok & check_tensor(tensors1[9], tensors2[9], L * C, "fcprojb", 1.5e-2f);
|
|
|
|
|
allok = allok & check_tensor(tensors1[10], tensors2[10], L * C, "ln1w", 6e-4f);
|
|
|
|
|
allok = allok & check_tensor(tensors1[11], tensors2[11], L * C, "ln1b", 9e-3f);
|
|
|
|
|
allok = allok & check_tensor(tensors1[12], tensors2[12], L * C, "ln2w", 2e-3f);
|
|
|
|
|
allok = allok & check_tensor(tensors1[13], tensors2[13], L * C, "ln2b", 2.5e-3f);
|
2024-04-27 23:17:22 +00:00
|
|
|
allok = allok & check_tensor(tensors1[14], tensors2[14], C, "lnfw", 0.12f); // hmm bit higher
|
2024-05-18 13:27:35 +03:00
|
|
|
allok = allok & check_tensor(tensors1[15], tensors2[15], C, "lnfb", 2e-2f);
|
2024-04-10 18:15:55 +00:00
|
|
|
}
|
2024-04-17 04:58:37 +00:00
|
|
|
|
2024-05-23 20:45:59 +00:00
|
|
|
gpt2_update(&model, 1e-4f, 0.9f, 0.95f, 1e-8f, 0.0f, 1.0f, step+1, &multi_gpu_config);
|
2024-04-17 04:58:37 +00:00
|
|
|
|
|
|
|
|
// print the timing information at the end
|
2024-04-30 17:46:36 +00:00
|
|
|
printf("step %d: loss %f (took %f ms)\n", step+1, model.mean_loss, time_elapsed_s * 1000);
|
2024-04-17 04:58:37 +00:00
|
|
|
losses[step] = model.mean_loss;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// expected losses are as follows, from Python
|
|
|
|
|
float expected_losses[10] = {
|
2024-05-03 00:39:06 +03:00
|
|
|
5.2700,
|
|
|
|
|
4.0607,
|
2024-05-23 20:45:59 +00:00
|
|
|
3.3202,
|
|
|
|
|
2.7176,
|
|
|
|
|
2.1811,
|
|
|
|
|
1.6538,
|
|
|
|
|
1.1680,
|
|
|
|
|
0.7367,
|
|
|
|
|
0.4008,
|
|
|
|
|
0.1874
|
2024-04-17 04:58:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// compare
|
|
|
|
|
for (int i = 0; i < 10; i++) {
|
2024-04-27 23:17:22 +00:00
|
|
|
if (fabsf(losses[i] - expected_losses[i]) >= loss_diff_threshold) {
|
2024-04-30 17:46:36 +00:00
|
|
|
printf("LOSS MISMATCH AT STEP %d: %f %f\n", i+1, losses[i], expected_losses[i]);
|
2024-04-17 04:58:37 +00:00
|
|
|
allok = 0;
|
|
|
|
|
} else {
|
2024-04-30 17:46:36 +00:00
|
|
|
printf("loss ok at step %d: %f %f\n", i+1, losses[i], expected_losses[i]);
|
2024-04-17 04:58:37 +00:00
|
|
|
}
|
2024-04-10 18:15:55 +00:00
|
|
|
}
|
|
|
|
|
|
2024-04-17 04:58:37 +00:00
|
|
|
// final approval
|
2024-04-10 18:15:55 +00:00
|
|
|
printf("overall okay: %d\n", allok);
|
|
|
|
|
|
|
|
|
|
// free everything
|
2024-06-03 18:10:33 +00:00
|
|
|
gpt2_free(&model);
|
2024-05-04 23:40:15 +01:00
|
|
|
common_free(model);
|
2024-04-10 18:15:55 +00:00
|
|
|
free(x);
|
|
|
|
|
free(y);
|
2024-04-27 00:54:06 +00:00
|
|
|
free(logits_cpu_raw);
|
|
|
|
|
free(logits_cpu);
|
2024-04-10 18:15:55 +00:00
|
|
|
free(expected_logits);
|
|
|
|
|
free(expected_loss);
|
|
|
|
|
free(expected_grads_memory);
|
2024-04-27 15:27:05 +00:00
|
|
|
free(grads_memory_cpu);
|
|
|
|
|
free(grads_memory_cpu_float);
|
2024-04-10 18:15:55 +00:00
|
|
|
return 0;
|
2024-04-28 20:15:37 +02:00
|
|
|
}
|