| |
| |
| |
| |
| |
|
|
| #include <hip/hip_runtime.h> |
| #include <hipblas.h> |
| #include <cmath> |
| #include <cstdio> |
| #include <cstdlib> |
|
|
| #define CHECK_HIP(cmd) do { \ |
| hipError_t e = cmd; \ |
| if (e != hipSuccess) { \ |
| fprintf(stderr, "HIP error %s:%d '%s'(%d)\n", __FILE__, __LINE__, hipGetErrorString(e), e); \ |
| exit(1); \ |
| } \ |
| } while(0) |
|
|
| |
| |
| |
|
|
| |
| __global__ void relu_kernel(float* y, const float* x, int n) { |
| int i = blockIdx.x * blockDim.x + threadIdx.x; |
| if (i < n) y[i] = fmaxf(x[i], 0.0f); |
| } |
|
|
| |
| __global__ void sigmoid_kernel(float* y, const float* x, int n) { |
| int i = blockIdx.x * blockDim.x + threadIdx.x; |
| if (i < n) y[i] = 1.0f / (1.0f + expf(-x[i])); |
| } |
|
|
| |
| __global__ void l2_normalize_rows_kernel(float* x, int rows, int cols) { |
| int row = blockIdx.x; |
| if (row >= rows) return; |
| float sum_sq = 0.0f; |
| for (int j = 0; j < cols; j++) { |
| float v = x[row * cols + j]; |
| sum_sq += v * v; |
| } |
| float norm = sqrtf(sum_sq) + 1e-8f; |
| for (int j = 0; j < cols; j++) { |
| x[row * cols + j] /= norm; |
| } |
| } |
|
|
| |
| __global__ void mask_noise_kernel(float* y, const float* x, const float* mask, int n, float noise_std, unsigned long seed) { |
| int i = blockIdx.x * blockDim.x + threadIdx.x; |
| if (i >= n) return; |
| |
| unsigned long s = seed + i * 2654435761UL; |
| float r = (float)(s & 0xFFFFFF) / 0xFFFFFF - 0.5f; |
| y[i] = x[i] * mask[i] + r * noise_std; |
| } |
|
|
| |
| __global__ void mse_grad_kernel(float* grad, const float* pred, const float* target, int n) { |
| int i = blockIdx.x * blockDim.x + threadIdx.x; |
| if (i < n) grad[i] = 2.0f * (pred[i] - target[i]) / static_cast<float>(n); |
| } |
|
|
| |
| __global__ void sgd_update_kernel(float* w, const float* grad, int n, float lr, float wd) { |
| int i = blockIdx.x * blockDim.x + threadIdx.x; |
| if (i < n) w[i] -= lr * (grad[i] + wd * w[i]); |
| } |
|
|
| |
| __global__ void topk_mask_kernel(float* y, int n, int k, int offset) { |
| |
| extern __shared__ float shared[]; |
| int tid = threadIdx.x; |
| int row = blockIdx.x; |
| |
| |
| if (tid < k * 2) { |
| int idx = row * n + offset + tid; |
| shared[tid] = (tid < n - offset) ? fabsf(y[idx]) : -1.0f; |
| } |
| __syncthreads(); |
| |
| |
| |
| if (tid == 0) { |
| |
| float local[256]; |
| int len = min(n - offset, 256); |
| for (int j = 0; j < len; j++) { |
| int idx = row * n + offset + j; |
| local[j] = fabsf(y[idx]); |
| } |
| |
| for (int j = 0; j < k && j < len; j++) { |
| int max_idx = j; |
| for (int m = j+1; m < len; m++) { |
| if (local[m] > local[max_idx]) max_idx = m; |
| } |
| float tmp = local[j]; |
| local[j] = local[max_idx]; |
| local[max_idx] = tmp; |
| } |
| float threshold = (k <= len) ? local[k-1] : 0.0f; |
| |
| for (int j = 0; j < len; j++) { |
| int idx = row * n + offset + j; |
| if (fabsf(y[idx]) < threshold && fabsf(y[idx]) > 0) { |
| y[idx] = 0.0f; |
| } |
| } |
| } |
| } |
|
|
| |
| |
| |
|
|
| extern "C" { |
|
|
| |
| int gpu_get_count() { |
| int count; |
| CHECK_HIP(hipGetDeviceCount(&count)); |
| return count; |
| } |
|
|
| void gpu_get_name(int id, char* name, int max_len) { |
| hipDeviceProp_t prop; |
| CHECK_HIP(hipGetDeviceProperties(&prop, id)); |
| strncpy(name, prop.name, max_len); |
| } |
|
|
| |
| void gpu_init(int device_id) { |
| CHECK_HIP(hipSetDevice(device_id)); |
| printf("[GPU] Initialized device %d\n", device_id); |
| } |
|
|
| |
| float* gpu_alloc(int n) { |
| float* ptr; |
| CHECK_HIP(hipMalloc(&ptr, n * sizeof(float))); |
| return ptr; |
| } |
|
|
| void gpu_free(float* ptr) { |
| CHECK_HIP(hipFree(ptr)); |
| } |
|
|
| |
| void gpu_memcpy_htod(float* d_ptr, const float* h_ptr, int n) { |
| CHECK_HIP(hipMemcpy(d_ptr, h_ptr, n * sizeof(float), hipMemcpyHostToDevice)); |
| } |
|
|
| void gpu_memcpy_dtoh(float* h_ptr, const float* d_ptr, int n) { |
| CHECK_HIP(hipMemcpy(h_ptr, d_ptr, n * sizeof(float), hipMemcpyDeviceToHost)); |
| } |
|
|
| |
| void gpu_relu(float* d_y, const float* d_x, int n) { |
| int block = 256; |
| int grid = (n + block - 1) / block; |
| relu_kernel<<<grid, block>>>(d_y, d_x, n); |
| CHECK_HIP(hipGetLastError()); |
| CHECK_HIP(hipDeviceSynchronize()); |
| } |
|
|
| |
| void gpu_sigmoid(float* d_y, const float* d_x, int n) { |
| int block = 256; |
| int grid = (n + block - 1) / block; |
| sigmoid_kernel<<<grid, block>>>(d_y, d_x, n); |
| CHECK_HIP(hipGetLastError()); |
| CHECK_HIP(hipDeviceSynchronize()); |
| } |
|
|
| |
| void gpu_l2_norm_rows(float* d_x, int rows, int cols) { |
| l2_normalize_rows_kernel<<<rows, 1>>>(d_x, rows, cols); |
| CHECK_HIP(hipGetLastError()); |
| CHECK_HIP(hipDeviceSynchronize()); |
| } |
|
|
| |
| void gpu_mask_noise(float* d_y, const float* d_x, const float* d_mask, int n, float noise_std, unsigned long seed) { |
| int block = 256; |
| int grid = (n + block - 1) / block; |
| mask_noise_kernel<<<grid, block>>>(d_y, d_x, d_mask, n, noise_std, seed); |
| CHECK_HIP(hipGetLastError()); |
| CHECK_HIP(hipDeviceSynchronize()); |
| } |
|
|
| |
| |
| void gpu_matmul(float* d_C, const float* d_A, const float* d_B, int M, int N, int K) { |
| static hipblasHandle_t handle = nullptr; |
| if (!handle) hipblasCreate(&handle); |
| |
| float alpha = 1.0f, beta = 0.0f; |
| hipblasSgemm(handle, HIPBLAS_OP_N, HIPBLAS_OP_N, |
| N, M, K, |
| &alpha, d_B, N, d_A, K, |
| &beta, d_C, N); |
| CHECK_HIP(hipDeviceSynchronize()); |
| } |
|
|
| |
| void gpu_sgd_update(float* d_w, const float* d_grad, int n, float lr, float wd) { |
| int block = 256; |
| int grid = (n + block - 1) / block; |
| sgd_update_kernel<<<grid, block>>>(d_w, d_grad, n, lr, wd); |
| CHECK_HIP(hipGetLastError()); |
| CHECK_HIP(hipDeviceSynchronize()); |
| } |
|
|
| |
| void gpu_fill_zero(float* d_ptr, int n) { |
| CHECK_HIP(hipMemset(d_ptr, 0, n * sizeof(float))); |
| } |
|
|
| |
| void gpu_mem_info() { |
| size_t free, total; |
| CHECK_HIP(hipMemGetInfo(&free, &total)); |
| printf("[GPU] Memory: %.1f GB free / %.1f GB total\n", |
| free / 1e9, total / 1e9); |
| } |
|
|
| } |
|
|