499 lines
18 KiB
Plaintext
499 lines
18 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <cuda_runtime.h>
|
|
#include <math.h>
|
|
#include <float.h>
|
|
#include <cublas_v2.h>
|
|
#include <cuda_runtime.h>
|
|
#include <iostream>
|
|
|
|
// Include CPU kernels
|
|
#include "cpu_kernels/attention.cuh"
|
|
#include "cpu_kernels/encoder.cuh"
|
|
#include "cpu_kernels/gelu.cuh"
|
|
#include "cpu_kernels/layernorm.cuh"
|
|
#include "cpu_kernels/matmul.cuh"
|
|
#include "cpu_kernels/residual.cuh"
|
|
|
|
// Include GPU kernels
|
|
#include "kernels/attention.cuh"
|
|
#include "kernels/encoder.cuh"
|
|
#include "kernels/gelu.cuh"
|
|
#include "kernels/layernorm.cuh"
|
|
#include "kernels/matmul.cuh"
|
|
#include "kernels/residual.cuh"
|
|
#include "kernels/softmax.cuh"
|
|
|
|
// Include CUDA utilities
|
|
#include "utils/cuda_utils.cuh"
|
|
|
|
int main() {
|
|
|
|
// set up the device
|
|
int deviceIdx = 0;
|
|
cudaCheck(cudaSetDevice(deviceIdx));
|
|
cudaDeviceProp deviceProp;
|
|
cudaGetDeviceProperties(&deviceProp, deviceIdx);
|
|
|
|
// setup cuBLAS and cuBLASLt
|
|
cublasCheck(cublasCreate(&cublas_handle));
|
|
// TF32 precision is equivalent to torch.set_float32_matmul_precision('high')
|
|
int enable_tf32 = 0;
|
|
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));
|
|
|
|
const int B = 4; // Batch size
|
|
const int T = 128; // Sequence length
|
|
const int C = 128; // Input channels
|
|
const int OC = 4 * C; // Output channels
|
|
|
|
const int NH = 12; // Number of heads
|
|
|
|
const float error_threshold = 0; // TODO: Set the error threshold for GPU vs CPU output comparisons
|
|
// This is in unit of percentage difference in output values
|
|
// Change this to a small value (like 0.01) for your own testing
|
|
|
|
const float ep = 0.0001; // Epsilon value for percentage calculation to avoid getting infinity
|
|
|
|
// used in multi-head self-attention
|
|
const int HS = C / NH; // head size
|
|
|
|
// Generate random input data
|
|
srand(time(NULL));
|
|
|
|
/*------------------------ encoder_forward test ------------------------*/
|
|
|
|
// Allocate memory for input data
|
|
int* enc_inp_cpu = (int*)malloc(B * T * sizeof(int));
|
|
float* wte_enc = (float*)malloc(C * C * sizeof(float));
|
|
float* wpe_enc = (float*)malloc(T * C * sizeof(float));
|
|
|
|
for (int i = 0; i < B * T; ++i) {
|
|
enc_inp_cpu[i] = (int)rand() / RAND_MAX;
|
|
}
|
|
for (int i = 0; i < C * C; ++i) {
|
|
wte_enc[i] = (float)rand() / RAND_MAX;
|
|
}
|
|
for (int i = 0; i < T * C; ++i) {
|
|
wpe_enc[i] = (float)rand() / RAND_MAX;
|
|
}
|
|
|
|
// copy data to GPU
|
|
int* enc_inp_gpu_d;
|
|
float* wte_enc_d;
|
|
float* wpe_enc_d;
|
|
cudaMalloc(&enc_inp_gpu_d, B * T * sizeof(int));
|
|
cudaMalloc(&wte_enc_d, C * C * sizeof(float));
|
|
cudaMalloc(&wpe_enc_d, T * C * sizeof(float));
|
|
cudaMemcpy(enc_inp_gpu_d, enc_inp_cpu, B * T * sizeof(int), cudaMemcpyHostToDevice);
|
|
cudaMemcpy(wte_enc_d, wte_enc, C * C * sizeof(float), cudaMemcpyHostToDevice);
|
|
cudaMemcpy(wpe_enc_d, wpe_enc, T * C * sizeof(float), cudaMemcpyHostToDevice);
|
|
|
|
|
|
// Allocate memory for output
|
|
float* enc_out_cpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* enc_out_gpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* enc_out_gpu_d;
|
|
cudaMalloc(&enc_out_gpu_d, B * T * C * sizeof(float));
|
|
|
|
// Call CPU function for reference output
|
|
encoder_forward_cpu(enc_out_cpu, enc_inp_cpu, wte_enc, wpe_enc, B, T, C);
|
|
|
|
// TODO: Call your GPU function
|
|
// encoder_forward(enc_out_gpu_d, enc_inp_gpu_d, wte_enc_d, wpe_enc_d, B, T, C);
|
|
|
|
// TODO: Copy output from your GPU function back to CPU
|
|
// cudaMemcpy(..., cudaMemcpyDeviceToHost);
|
|
|
|
int enc_totElements = B * T * C;
|
|
int enc_error = 0;
|
|
for (int i = 0; i < enc_totElements; i++) {
|
|
if (fabs(enc_out_cpu[i] - enc_out_gpu[i]) / (enc_out_cpu[i] + ep) > error_threshold) {
|
|
enc_error++;
|
|
}
|
|
}
|
|
|
|
if (enc_error > 0) {
|
|
printf("+++++++++++++++ encoder_forward test failed with %d differing values +++++++++++++++\n", enc_error);
|
|
printf("+++++++++++++++ Check your implementation or error_threshold value +++++++++++++++\n");
|
|
} else {
|
|
printf("--------------------encoder_forward test passed!--------------------\n");
|
|
}
|
|
|
|
/*------------------------ layernorm_forward test ------------------------*/
|
|
|
|
// Allocate memory for input data
|
|
float* lay_inp_cpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* weight_ln = (float*)malloc(C * sizeof(float));
|
|
float* bias_ln = (float*)malloc(C * sizeof(float));
|
|
float* rstd_ln = (float*)malloc(B * T * sizeof(float));
|
|
float* mean_ln = (float*)malloc(B * T * sizeof(float));
|
|
|
|
// Generate random input data
|
|
for (int i = 0; i < B * T * C; ++i) {
|
|
lay_inp_cpu[i] = (float)rand() / RAND_MAX;
|
|
}
|
|
for (int i = 0; i < B * T; ++i) {
|
|
rstd_ln[i] = (float)rand() / RAND_MAX;
|
|
mean_ln[i] = (float)rand() / RAND_MAX;
|
|
}
|
|
for (int i = 0; i < C; ++i) {
|
|
weight_ln[i] = (float)rand() / RAND_MAX;
|
|
bias_ln[i] = (float)rand() / RAND_MAX;
|
|
}
|
|
|
|
// copy data to GPU
|
|
float* lay_inp_gpu_d;
|
|
float* weight_ln_d;
|
|
float* bias_ln_d;
|
|
float* rstd_ln_d;
|
|
float* mean_ln_d;
|
|
cudaMalloc(&lay_inp_gpu_d, B * T * C * sizeof(float));
|
|
cudaMalloc(&weight_ln_d, C * sizeof(float));
|
|
cudaMalloc(&bias_ln_d, C * sizeof(float));
|
|
cudaMalloc(&rstd_ln_d, B * T * sizeof(float));
|
|
cudaMalloc(&mean_ln_d, B * T * sizeof(float));
|
|
cudaMemcpy(lay_inp_gpu_d, lay_inp_cpu, B * T * C * sizeof(float), cudaMemcpyHostToDevice);
|
|
cudaMemcpy(weight_ln_d, weight_ln, C * sizeof(float), cudaMemcpyHostToDevice);
|
|
cudaMemcpy(bias_ln_d, bias_ln, C * sizeof(float), cudaMemcpyHostToDevice);
|
|
cudaMemcpy(rstd_ln_d, rstd_ln, B * T * sizeof(float), cudaMemcpyHostToDevice);
|
|
cudaMemcpy(mean_ln_d, mean_ln, B * T * sizeof(float), cudaMemcpyHostToDevice);
|
|
|
|
// Allocate memory for output
|
|
float* lay_out_cpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* lay_out_gpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* lay_out_gpu_d;
|
|
cudaMalloc(&lay_out_gpu_d, B * T * C * sizeof(float));
|
|
|
|
// Call CPU function for reference output
|
|
layernorm_forward_cpu(lay_out_cpu, mean_ln, rstd_ln, lay_inp_cpu, weight_ln, bias_ln, B, T, C);
|
|
|
|
// TODO: Call your GPU function
|
|
// layernorm_forward(lay_out_gpu_d, mean_ln_d, rstd_ln_d, lay_inp_gpu_d, weight_ln_d, bias_ln_d, B, T, C);
|
|
|
|
// TODO: Copy output from your GPU function back to CPU
|
|
// cudaMemcpy(..., cudaMemcpyDeviceToHost);
|
|
|
|
int lay_totElements = B * T * C;
|
|
int lay_error = 0;
|
|
for (int i = 0; i < lay_totElements; i++) {
|
|
if (fabs(lay_out_cpu[i] - lay_out_gpu[i])/(lay_out_cpu[i] + ep) > error_threshold) {
|
|
lay_error++;
|
|
}
|
|
}
|
|
|
|
if (lay_error > 0) {
|
|
printf("+++++++++++++++ layernorm_forward test failed with %d differing values +++++++++++++++\n", lay_error);
|
|
printf("+++++++++++++++ Check your implementation or error_threshold value +++++++++++++++\n");
|
|
} else {
|
|
printf("--------------------layernorm_forward test passed!--------------------\n");
|
|
}
|
|
|
|
/*------------------------ attention_forward test ------------------------*/
|
|
|
|
// Allocate memory for input data
|
|
int inp_size = B * T * max(3 * C, NH * T);
|
|
float* att_inp_cpu = (float*)malloc(inp_size * sizeof(float));
|
|
float* qkvr = (float*)malloc(3 * B * T * C * sizeof(float));
|
|
float* att = (float*)malloc(B * NH * NH * T * T * sizeof(float));
|
|
// create separate copy of input for GPU to avoid input memory being overwritten
|
|
float* att_inp_gpu = (float*)malloc(inp_size * sizeof(float));
|
|
|
|
// Generate random input data
|
|
for (int i = 0; i < inp_size; ++i) {
|
|
att_inp_cpu[i] = (float)rand() / RAND_MAX;
|
|
att_inp_gpu[i] = att_inp_cpu[i];
|
|
}
|
|
|
|
// copy data to GPU
|
|
float* att_inp_gpu_d;
|
|
float* qkvr_d;
|
|
float* att_d;
|
|
cudaMalloc(&att_inp_gpu_d, inp_size * sizeof(float));
|
|
cudaMalloc(&qkvr_d, 3 * B * T * C * sizeof(float));
|
|
cudaMalloc(&att_d, B * NH * NH * T * T * sizeof(float));
|
|
cudaMemcpy(att_inp_gpu_d, att_inp_gpu, inp_size * sizeof(float), cudaMemcpyHostToDevice);
|
|
|
|
// Allocate memory for output
|
|
float* att_out_cpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* att_out_gpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* att_out_gpu_d;
|
|
cudaMalloc(&att_out_gpu_d, B * T * C * sizeof(float));
|
|
|
|
// Call CPU function for reference output
|
|
attention_forward_cpu(att_out_cpu, qkvr, att, att_inp_cpu, B, T, C, NH);
|
|
|
|
// TODO: Call your GPU function
|
|
// attention_forward(att_out_gpu_d, qkvr_d, att_d, att_inp_gpu_d, B, T, C, NH);
|
|
|
|
// TODO: Copy output from your GPU function back to CPU
|
|
// cudaMemcpy(..., cudaMemcpyDeviceToHost);
|
|
|
|
int att_totElements = B * T * C;
|
|
int att_diff = 0;
|
|
// Loop through the results to count differences
|
|
for (int i = 0; i < att_totElements; ++i) {
|
|
// Check if the result differs by more than the tolerance
|
|
if (fabs(att_out_cpu[i] - att_out_gpu[i])/(att_out_cpu[i] + ep) > error_threshold) {
|
|
++att_diff;
|
|
}
|
|
}
|
|
|
|
if (att_diff > 0) {
|
|
printf("+++++++++++++++ attention_forward test failed with %d differing values +++++++++++++++\n", att_diff);
|
|
printf("+++++++++++++++ Check your implementation or error_threshold value +++++++++++++++\n");
|
|
printf("++++++++ Try testing each attention component separately for easier debugging ++++++++\n");
|
|
} else {
|
|
printf("--------------------attention_forward test passed!--------------------\n");
|
|
}
|
|
|
|
/*------------------------ residual_forward test ------------------------*/
|
|
|
|
// Allocate memory for input data
|
|
float* res_inp1_cpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* res_inp2_cpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* res_out_cpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* res_out_gpu = (float*)malloc(B * T * C * sizeof(float));
|
|
|
|
// Generate random input data
|
|
for (int i = 0; i < B * T * C; ++i) {
|
|
res_inp1_cpu[i] = (float)rand() / RAND_MAX;
|
|
res_inp2_cpu[i] = (float)rand() / RAND_MAX;
|
|
}
|
|
|
|
// copy data to GPU
|
|
float* res_inp1_gpu_d;
|
|
float* res_inp2_gpu_d;
|
|
float* res_out_gpu_d;
|
|
cudaMalloc(&res_inp1_gpu_d, B * T * C * sizeof(float));
|
|
cudaMalloc(&res_inp2_gpu_d, B * T * C * sizeof(float));
|
|
cudaMalloc(&res_out_gpu_d, B * T * C * sizeof(float));
|
|
cudaMemcpy(res_inp1_gpu_d, res_inp1_cpu, B * T * C * sizeof(float), cudaMemcpyHostToDevice);
|
|
cudaMemcpy(res_inp2_gpu_d, res_inp2_cpu, B * T * C * sizeof(float), cudaMemcpyHostToDevice);
|
|
|
|
// Call CPU function for reference output
|
|
residual_forward_cpu(res_out_cpu, res_inp1_cpu, res_inp2_cpu, B * T * C);
|
|
|
|
// TODO: Call your GPU function
|
|
// residual_forward(res_out_gpu_d, res_inp1_gpu_d, res_inp2_gpu_d, B * T * C);
|
|
|
|
// TODO: Copy output from your GPU function back to CPU
|
|
// cudaMemcpy(..., cudaMemcpyDeviceToHost);
|
|
|
|
int res_totElements = B * T * C;
|
|
int res_diff = 0;
|
|
// Loop through the results to count differences
|
|
for (int i = 0; i < res_totElements; ++i) {
|
|
// Check if the result differs by more than the tolerance
|
|
if (fabs(res_out_cpu[i] - res_out_gpu[i])/ (res_out_cpu[i] + ep) > error_threshold) {
|
|
++res_diff;
|
|
}
|
|
}
|
|
|
|
if (res_diff > 0) {
|
|
printf("+++++++++++++++ residual_forward test failed with %d differing values +++++++++++++++\n", res_diff);
|
|
printf("+++++++++++++++ Check your implementation or error_threshold value +++++++++++++++\n");
|
|
} else {
|
|
printf("--------------------residual_forward test passed!--------------------\n");
|
|
}
|
|
|
|
/*------------------------ gelu_forward test ------------------------*/
|
|
|
|
// Allocate memory for input data
|
|
float* gelu_inp_cpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* gelu_out_cpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* gelu_out_gpu = (float*)malloc(B * T * C * sizeof(float));
|
|
|
|
// Generate random input data
|
|
for (int i = 0; i < B * T * C; ++i) {
|
|
gelu_inp_cpu[i] = (float)rand() / RAND_MAX;
|
|
}
|
|
|
|
// copy data to GPU
|
|
float* gelu_inp_gpu_d;
|
|
float* gelu_out_gpu_d;
|
|
cudaMalloc(&gelu_inp_gpu_d, B * T * C * sizeof(float));
|
|
cudaMalloc(&gelu_out_gpu_d, B * T * C * sizeof(float));
|
|
cudaMemcpy(gelu_inp_gpu_d, gelu_inp_cpu, B * T * C * sizeof(float), cudaMemcpyHostToDevice);
|
|
|
|
// Call CPU function for reference output
|
|
gelu_forward_cpu(gelu_out_cpu, gelu_inp_cpu, B * T * C);
|
|
|
|
// TODO: Call your GPU function
|
|
// gelu_forward(gelu_out_gpu_d, gelu_inp_gpu_d, B * T * C);
|
|
|
|
// TODO: Copy output from your GPU function back to CPU
|
|
// cudaMemcpy(..., cudaMemcpyDeviceToHost);
|
|
|
|
int gelu_totElements = B * T * C;
|
|
int gelu_diff = 0;
|
|
for (int i = 0; i < gelu_totElements; ++i) {
|
|
if (fabs(gelu_out_cpu[i] - gelu_out_gpu[i])/(gelu_out_cpu[i] + ep) > error_threshold) {
|
|
++gelu_diff;
|
|
}
|
|
}
|
|
|
|
if (gelu_diff > 0) {
|
|
printf("+++++++++++++++ gelu_forward test failed with %d differing values +++++++++++++++\n", gelu_diff);
|
|
printf("+++++++++++++++ Check your implementation or error_threshold value +++++++++++++++\n");
|
|
} else {
|
|
printf("--------------------gelu_forward test passed!--------------------\n");
|
|
}
|
|
|
|
/*------------------------ matmul_forward test ------------------------*/
|
|
|
|
// Allocate memory for input data
|
|
float* mat_inp_cpu = (float*)malloc(B * T * C * sizeof(float));
|
|
float* matmul_weight = (float*)malloc(4 * C * C * sizeof(float));
|
|
float* matmul_bias = (float*)malloc(4 * C * sizeof(float));
|
|
float* mat_out_cpu = (float*)malloc(B * T * 4 * C * sizeof(float));
|
|
|
|
// Generate random input data
|
|
for (int i = 0; i < B * T * C; ++i) {
|
|
mat_inp_cpu[i] = (float)rand() / RAND_MAX;
|
|
}
|
|
for (int i = 0; i < 4 * C * C; ++i) {
|
|
matmul_weight[i] = (float)rand() / RAND_MAX;
|
|
}
|
|
for (int i = 0; i < 4 * C; ++i) {
|
|
matmul_bias[i] = (float)rand() / RAND_MAX;
|
|
}
|
|
|
|
// copy data to GPU
|
|
float* mat_inp_gpu_d;
|
|
float* matmul_weight_d;
|
|
float* matmul_bias_d;
|
|
float* mat_out_gpu_d;
|
|
float* mat_out_gpu = (float*)malloc(B * T * 4 * C * sizeof(float));
|
|
cudaMalloc(&mat_inp_gpu_d, B * T * C * sizeof(float));
|
|
cudaMalloc(&matmul_weight_d, 4 * C * C * sizeof(float));
|
|
cudaMalloc(&matmul_bias_d, 4 * C * sizeof(float));
|
|
cudaMalloc(&mat_out_gpu_d, B * T * 4 * C * sizeof(float));
|
|
cudaMemcpy(mat_inp_gpu_d, mat_inp_cpu, B * T * C * sizeof(float), cudaMemcpyHostToDevice);
|
|
cudaMemcpy(matmul_weight_d, matmul_weight, 4 * C * C * sizeof(float), cudaMemcpyHostToDevice);
|
|
cudaMemcpy(matmul_bias_d, matmul_bias, 4 * C * sizeof(float), cudaMemcpyHostToDevice);
|
|
|
|
// Call CPU function for reference output
|
|
matmul_forward_cpu(mat_out_cpu, mat_inp_cpu, matmul_weight, matmul_bias, B, T, C, OC);
|
|
|
|
// TODO: Call your GPU function
|
|
// matmul_forward(mat_out_gpu_d, mat_inp_gpu_d, matmul_weight_d, matmul_bias_d, B, T, C, OC);
|
|
|
|
// TODO: Copy output from your GPU function back to CPU
|
|
// cudaMemcpy(..., cudaMemcpyDeviceToHost);
|
|
|
|
int mat_totElements = B * T * 4 * C;
|
|
int mat_diff = 0;
|
|
for (int i = 0; i < mat_totElements; ++i) {
|
|
if (fabs(mat_out_cpu[i] - mat_out_gpu[i])/(mat_out_cpu[i] + ep) > error_threshold) {
|
|
++mat_diff;
|
|
}
|
|
}
|
|
|
|
if (mat_diff > 0) {
|
|
printf("+++++++++++++++ matmul_forward test failed with %d differing values +++++++++++++++\n", mat_diff);
|
|
printf("+++++++++++++++ Check your implementation or error_threshold value +++++++++++++++\n");
|
|
} else {
|
|
printf("--------------------matmul_forward test passed!--------------------\n");
|
|
}
|
|
|
|
printf("********************* All Random Tests Finished! *********************\n");
|
|
|
|
// Free allocated memory
|
|
|
|
free(enc_inp_cpu);
|
|
free(enc_out_cpu);
|
|
free(wte_enc);
|
|
free(wpe_enc);
|
|
free(enc_out_gpu);
|
|
cudaFree(enc_inp_gpu_d);
|
|
cudaFree(wte_enc_d);
|
|
cudaFree(wpe_enc_d);
|
|
cudaFree(enc_out_gpu_d);
|
|
|
|
free(lay_inp_cpu);
|
|
free(lay_out_cpu);
|
|
free(weight_ln);
|
|
free(bias_ln);
|
|
free(rstd_ln);
|
|
free(mean_ln);
|
|
free(lay_out_gpu);
|
|
cudaFree(lay_inp_gpu_d);
|
|
cudaFree(weight_ln_d);
|
|
cudaFree(bias_ln_d);
|
|
cudaFree(rstd_ln_d);
|
|
cudaFree(mean_ln_d);
|
|
cudaFree(lay_out_gpu_d);
|
|
|
|
free(perm_inp_cpu);
|
|
free(perm_q_cpu);
|
|
free(perm_k_cpu);
|
|
free(perm_v_cpu);
|
|
free(perm_q_gpu);
|
|
free(perm_k_gpu);
|
|
free(perm_v_gpu);
|
|
cudaFree(perm_inp_gpu_d);
|
|
cudaFree(perm_q_d);
|
|
cudaFree(perm_k_d);
|
|
cudaFree(perm_v_d);
|
|
|
|
free(unperm_inp_cpu);
|
|
free(unperm_out_cpu);
|
|
free(unperm_out_gpu);
|
|
cudaFree(unperm_inp_gpu_d);
|
|
cudaFree(unperm_out_gpu_d);
|
|
|
|
free(softmax_inp_cpu);
|
|
free(softmax_inp_gpu);
|
|
free(softmax_out_cpu);
|
|
free(softmax_out_gpu);
|
|
cudaFree(softmax_inp_gpu_d);
|
|
cudaFree(softmax_out_gpu_d);
|
|
|
|
free(att_inp_cpu);
|
|
free(att_out_cpu);
|
|
free(att_inp_gpu);
|
|
free(att_out_gpu);
|
|
free(qkvr);
|
|
free(att);
|
|
cudaFree(att_inp_gpu_d);
|
|
cudaFree(qkvr_d);
|
|
cudaFree(att_d);
|
|
cudaFree(att_out_gpu_d);
|
|
|
|
free(res_inp1_cpu);
|
|
free(res_inp2_cpu);
|
|
free(res_out_cpu);
|
|
free(res_out_gpu);
|
|
cudaFree(res_inp1_gpu_d);
|
|
cudaFree(res_inp2_gpu_d);
|
|
cudaFree(res_out_gpu_d);
|
|
|
|
free(gelu_inp_cpu);
|
|
free(gelu_out_cpu);
|
|
free(gelu_out_gpu);
|
|
cudaFree(gelu_inp_gpu_d);
|
|
cudaFree(gelu_out_gpu_d);
|
|
|
|
free(mat_inp_cpu);
|
|
free(mat_out_gpu);
|
|
free(matmul_weight);
|
|
free(matmul_bias);
|
|
cudaFree(mat_inp_gpu_d);
|
|
cudaFree(matmul_weight_d);
|
|
cudaFree(matmul_bias_d);
|
|
cudaFree(mat_out_gpu_d);
|
|
|
|
return 0;
|
|
}
|
|
|