/* * MatrixCuda.inl.cuh - MatrixCuda类的内联实现 * 包含CUDA内核函数和模板成员函数的实现 */ #ifndef MATRIX_CUDA_INL_CUH #define MATRIX_CUDA_INL_CUH #include "MatrixCuda.cuh" #include #include #include namespace qing { // ============================================================================ // CUDA内核函数实现 // ============================================================================ namespace cuda_kernels { // 矩阵加法内核 template __global__ void matrix_add_kernel(const T* A, const T* B, T* C, long rows, long cols, long total_elements) { long idx = blockIdx.x * blockDim.x + threadIdx.x; long stride = blockDim.x * gridDim.x; for (long i = idx; i < total_elements; i += stride) { C[i] = A[i] + B[i]; } } // 矩阵减法内核 template __global__ void matrix_sub_kernel(const T* A, const T* B, T* C, long rows, long cols, long total_elements) { long idx = blockIdx.x * blockDim.x + threadIdx.x; long stride = blockDim.x * gridDim.x; for (long i = idx; i < total_elements; i += stride) { C[i] = A[i] - B[i]; } } // 矩阵标量乘法内核 template __global__ void matrix_scalar_mul_kernel(const T* A, T scalar, T* C, long total_elements) { long idx = blockIdx.x * blockDim.x + threadIdx.x; long stride = blockDim.x * gridDim.x; for (long i = idx; i < total_elements; i += stride) { C[i] = A[i] * scalar; } } // 矩阵标量加法内核 template __global__ void matrix_scalar_add_kernel(const T* A, T scalar, T* C, long total_elements) { long idx = blockIdx.x * blockDim.x + threadIdx.x; long stride = blockDim.x * gridDim.x; for (long i = idx; i < total_elements; i += stride) { C[i] = A[i] + scalar; } } // 矩阵转置内核 template __global__ void matrix_transpose_kernel(const T* A, T* C, long rows, long cols) { long row = blockIdx.y * blockDim.y + threadIdx.y; long col = blockIdx.x * blockDim.x + threadIdx.x; if (row < rows && col < cols) { // A[row, col] -> C[col, row] C[col * rows + row] = A[row * cols + col]; } } // 矩阵元素对应乘积内核 template __global__ void matrix_hadamard_kernel(const T* A, const T* B, T* C, long total_elements) { long idx = blockIdx.x * blockDim.x + threadIdx.x; long stride = blockDim.x * gridDim.x; for (long i = idx; i < total_elements; i += stride) { C[i] = A[i] * B[i]; } } // 矩阵复制内核 template __global__ void matrix_copy_kernel(const T* src, T* dst, long total_elements) { long idx = blockIdx.x * blockDim.x + threadIdx.x; long stride = blockDim.x * gridDim.x; for (long i = idx; i < total_elements; i += stride) { dst[i] = src[i]; } } } // namespace cuda_kernels // ============================================================================ // MatrixCuda类成员函数实现 // ============================================================================ // 构造函数和析构函数 template CUDA_HOST MatrixCuda::MatrixCuda() : rows_(0), cols_(0), device_data_(nullptr), device_allocated_(false), host_modified_(false), device_modified_(false) {} template CUDA_HOST MatrixCuda::MatrixCuda(long rows, long cols) : rows_(rows), cols_(cols), device_data_(nullptr), device_allocated_(false), host_modified_(false), device_modified_(false) { if (rows <= 0 || cols <= 0) { throw std::invalid_argument("Matrix dimensions must be positive"); } host_data_.resize(rows * cols, T(0)); } template CUDA_HOST MatrixCuda::MatrixCuda(long rows, long cols, const std::vector& data) : rows_(rows), cols_(cols), device_data_(nullptr), device_allocated_(false), host_modified_(false), device_modified_(false) { initialize_from_vector(data); } template CUDA_HOST MatrixCuda::MatrixCuda(const MatrixCuda& other) : rows_(other.rows_), cols_(other.cols_), host_data_(other.host_data_), device_data_(nullptr), device_allocated_(false), host_modified_(other.host_modified_), device_modified_(false) { if (other.device_allocated_) { allocate_device_memory(); copy_to_device(); } } template CUDA_HOST MatrixCuda::MatrixCuda(MatrixCuda&& other) noexcept : rows_(other.rows_), cols_(other.cols_), host_data_(std::move(other.host_data_)), device_data_(other.device_data_), device_allocated_(other.device_allocated_), host_modified_(other.host_modified_), device_modified_(other.device_modified_) { other.rows_ = 0; other.cols_ = 0; other.device_data_ = nullptr; other.device_allocated_ = false; other.host_modified_ = false; other.device_modified_ = false; } template CUDA_HOST MatrixCuda::~MatrixCuda() { free_device_memory(); } // 赋值运算符 template CUDA_HOST MatrixCuda& MatrixCuda::operator=(const MatrixCuda& other) { if (this != &other) { free_device_memory(); rows_ = other.rows_; cols_ = other.cols_; host_data_ = other.host_data_; host_modified_ = other.host_modified_; device_modified_ = false; if (other.device_allocated_) { allocate_device_memory(); copy_to_device(); } } return *this; } template CUDA_HOST MatrixCuda& MatrixCuda::operator=(MatrixCuda&& other) noexcept { if (this != &other) { free_device_memory(); rows_ = other.rows_; cols_ = other.cols_; host_data_ = std::move(other.host_data_); device_data_ = other.device_data_; device_allocated_ = other.device_allocated_; host_modified_ = other.host_modified_; device_modified_ = other.device_modified_; other.rows_ = 0; other.cols_ = 0; other.device_data_ = nullptr; other.device_allocated_ = false; other.host_modified_ = false; other.device_modified_ = false; } return *this; } // 内存管理函数 template CUDA_HOST void MatrixCuda::allocate_device_memory() { if (device_allocated_ || get_total_elements() == 0) { return; } cudaError_t err = cudaMalloc(&device_data_, get_total_elements() * sizeof(T)); CHECK_CUDA_ERROR(err); device_allocated_ = true; device_modified_ = false; } template CUDA_HOST void MatrixCuda::free_device_memory() { if (device_allocated_ && device_data_ != nullptr) { cudaError_t err = cudaFree(device_data_); CHECK_CUDA_ERROR(err); device_data_ = nullptr; device_allocated_ = false; device_modified_ = false; } } template CUDA_HOST void MatrixCuda::copy_to_device() { if (!device_allocated_) { allocate_device_memory(); } if (host_modified_ && get_total_elements() > 0) { cudaError_t err = cudaMemcpy(device_data_, host_data_.data(), get_total_elements() * sizeof(T), cudaMemcpyHostToDevice); CHECK_CUDA_ERROR(err); host_modified_ = false; device_modified_ = true; } } template CUDA_HOST void MatrixCuda::copy_from_device() { if (device_allocated_ && device_modified_ && get_total_elements() > 0) { cudaError_t err = cudaMemcpy(host_data_.data(), device_data_, get_total_elements() * sizeof(T), cudaMemcpyDeviceToHost); CHECK_CUDA_ERROR(err); device_modified_ = false; host_modified_ = true; } } template CUDA_HOST void MatrixCuda::sync_device_to_host() { copy_from_device(); } template CUDA_HOST void MatrixCuda::sync_host_to_device() { copy_to_device(); } // 访问器函数 template CUDA_HOST T MatrixCuda::get_element(long row, long col) const { check_index(row, col); return host_data_[row * cols_ + col]; } template CUDA_HOST void MatrixCuda::set_element(long row, long col, T value) { check_index(row, col); host_data_[row * cols_ + col] = value; host_modified_ = true; } // 形状检查函数 template CUDA_HOST bool MatrixCuda::has_same_shape(const MatrixCuda& other) const { return rows_ == other.rows_ && cols_ == other.cols_; } template CUDA_HOST bool MatrixCuda::has_dot_shape(const MatrixCuda& other) const { return cols_ == other.rows_; } template CUDA_HOST void MatrixCuda::assert_same_shape(const MatrixCuda& other) const { if (!has_same_shape(other)) { throw std::invalid_argument("Matrices must have the same shape"); } } template CUDA_HOST void MatrixCuda::assert_dot_shape(const MatrixCuda& other) const { if (!has_dot_shape(other)) { throw std::invalid_argument("Matrices cannot be multiplied: cols of first != rows of second"); } } // 矩阵运算函数 template CUDA_HOST MatrixCuda MatrixCuda::add(const MatrixCuda& other) const { assert_same_shape(other); MatrixCuda result(rows_, cols_); // 确保数据在设备上 sync_host_to_device(); other.sync_host_to_device(); result.allocate_device_memory(); // 设置CUDA内核参数 long total_elements = get_total_elements(); dim3 block_size = get_block_size(total_elements); dim3 grid_size = get_grid_size(total_elements, block_size); // 启动内核 cuda_kernels::matrix_add_kernel<<>>( device_data_, other.device_data_, result.device_data_, rows_, cols_, total_elements ); CHECK_CUDA_ERROR(cudaGetLastError()); CHECK_CUDA_ERROR(cudaDeviceSynchronize()); result.device_modified_ = true; result.sync_device_to_host(); return result; } template CUDA_HOST MatrixCuda MatrixCuda::subtract(const MatrixCuda& other) const { assert_same_shape(other); MatrixCuda result(rows_, cols_); // 确保数据在设备上 sync_host_to_device(); other.sync_host_to_device(); result.allocate_device_memory(); // 设置CUDA内核参数 long total_elements = get_total_elements(); dim3 block_size = get_block_size(total_elements); dim3 grid_size = get_grid_size(total_elements, block_size); // 启动内核 cuda_kernels::matrix_sub_kernel<<>>( device_data_, other.device_data_, result.device_data_, rows_, cols_, total_elements ); CHECK_CUDA_ERROR(cudaGetLastError()); CHECK_CUDA_ERROR(cudaDeviceSynchronize()); result.device_modified_ = true; result.sync_device_to_host(); return result; } template CUDA_HOST MatrixCuda MatrixCuda::multiply_scalar(T scalar) const { MatrixCuda result(rows_, cols_); // 确保数据在设备上 sync_host_to_device(); result.allocate_device_memory(); // 设置CUDA内核参数 long total_elements = get_total_elements(); dim3 block_size = get_block_size(total_elements); dim3 grid_size = get_grid_size(total_elements, block_size); // 启动内核 cuda_kernels::matrix_scalar_mul_kernel<<>>( device_data_, scalar, result.device_data_, total_elements ); CHECK_CUDA_ERROR(cudaGetLastError()); CHECK_CUDA_ERROR(cudaDeviceSynchronize()); result.device_modified_ = true; result.sync_device_to_host(); return result; } template CUDA_HOST MatrixCuda MatrixCuda::add_scalar(T scalar) const { MatrixCuda result(rows_, cols_); // 确保数据在设备上 sync_host_to_device(); result.allocate_device_memory(); // 设置CUDA内核参数 long total_elements = get_total_elements(); dim3 block_size = get_block_size(total_elements); dim3 grid_size = get_grid_size(total_elements, block_size); // 启动内核 cuda_kernels::matrix_scalar_add_kernel<<>>( device_data_, scalar, result.device_data_, total_elements ); CHECK_CUDA_ERROR(cudaGetLastError()); CHECK_CUDA_ERROR(cudaDeviceSynchronize()); result.device_modified_ = true; result.sync_device_to_host(); return result; } template CUDA_HOST MatrixCuda MatrixCuda::transpose() const { MatrixCuda result(cols_, rows_); // 确保数据在设备上 sync_host_to_device(); result.allocate_device_memory(); // 设置CUDA内核参数(2D网格用于转置) dim3 block_size(16, 16); dim3 grid_size((cols_ + block_size.x - 1) / block_size.x, (rows_ + block_size.y - 1) / block_size.y); // 启动转置内核 cuda_kernels::matrix_transpose_kernel<<>>( device_data_, result.device_data_, rows_, cols_ ); CHECK_CUDA_ERROR(cudaGetLastError()); CHECK_CUDA_ERROR(cudaDeviceSynchronize()); result.device_modified_ = true; result.sync_device_to_host(); return result; } template CUDA_HOST MatrixCuda MatrixCuda::hadamard_product(const MatrixCuda& other) const { assert_same_shape(other); MatrixCuda result(rows_, cols_); // 确保数据在设备上 sync_host_to_device(); other.sync_host_to_device(); result.allocate_device_memory(); // 设置CUDA内核参数 long total_elements = get_total_elements(); dim3 block_size = get_block_size(total_elements); dim3 grid_size = get_grid_size(total_elements, block_size); // 启动内核 cuda_kernels::matrix_hadamard_kernel<<>>( device_data_, other.device_data_, result.device_data_, total_elements ); CHECK_CUDA_ERROR(cudaGetLastError()); CHECK_CUDA_ERROR(cudaDeviceSynchronize()); result.device_modified_ = true; result.sync_device_to_host(); return result; } // 运算符重载 template CUDA_HOST MatrixCuda MatrixCuda::operator+(const MatrixCuda& other) const { return add(other); } template CUDA_HOST MatrixCuda MatrixCuda::operator+(T scalar) const { return add_scalar(scalar); } template CUDA_HOST MatrixCuda MatrixCuda::operator-(const MatrixCuda& other) const { return subtract(other); } template CUDA_HOST MatrixCuda MatrixCuda::operator-(T scalar) const { return add_scalar(-scalar); } template CUDA_HOST MatrixCuda MatrixCuda::operator*(T scalar) const { return multiply_scalar(scalar); } template CUDA_HOST MatrixCuda MatrixCuda::operator/(T scalar) const { if (scalar == T(0)) { throw std::invalid_argument("Division by zero"); } return multiply_scalar(T(1) / scalar); } // 复合赋值运算符 template CUDA_HOST MatrixCuda& MatrixCuda::operator+=(const MatrixCuda& other) { *this = *this + other; return *this; } template CUDA_HOST MatrixCuda& MatrixCuda::operator+=(T scalar) { *this = *this + scalar; return *this; } template CUDA_HOST MatrixCuda& MatrixCuda::operator-=(const MatrixCuda& other) { *this = *this - other; return *this; } template CUDA_HOST MatrixCuda& MatrixCuda::operator-=(T scalar) { *this = *this - scalar; return *this; } template CUDA_HOST MatrixCuda& MatrixCuda::operator*=(T scalar) { *this = *this * scalar; return *this; } template CUDA_HOST MatrixCuda& MatrixCuda::operator/=(T scalar) { *this = *this / scalar; return *this; } // 矩阵乘法(基础实现,使用朴素算法) template CUDA_HOST MatrixCuda MatrixCuda::matmul(const MatrixCuda& other) const { assert_dot_shape(other); MatrixCuda result(rows_, other.cols_); // 同步数据到主机(使用朴素算法在主机上计算) sync_device_to_host(); other.sync_device_to_host(); // 朴素矩阵乘法(O(n³)) for (long i = 0; i < rows_; ++i) { for (long j = 0; j < other.cols_; ++j) { T sum = T(0); for (long k = 0; k < cols_; ++k) { sum += get_element(i, k) * other.get_element(k, j); } result.set_element(i, j, sum); } } // 标记结果已修改 result.host_modified_ = true; result.sync_host_to_device(); return result; } template CUDA_HOST MatrixCuda MatrixCuda::operator*(const MatrixCuda& other) const { return matmul(other); } // 工具函数 template CUDA_HOST void MatrixCuda::print(const std::string& name) const { sync_device_to_host(); if (!name.empty()) { std::cout << name << " (" << rows_ << "x" << cols_ << "):" << std::endl; } else { std::cout << "Matrix (" << rows_ << "x" << cols_ << "):" << std::endl; } for (long i = 0; i < rows_; ++i) { std::cout << " ["; for (long j = 0; j < cols_; ++j) { std::cout << get_element(i, j); if (j < cols_ - 1) std::cout << ", "; } std::cout << "]" << std::endl; } } template CUDA_HOST void MatrixCuda::fill(T value) { std::fill(host_data_.begin(), host_data_.end(), value); host_modified_ = true; } template CUDA_HOST void MatrixCuda::fill_random(T min, T max) { std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution dist(min, max); for (auto& val : host_data_) { val = dist(gen); } host_modified_ = true; } template CUDA_HOST bool MatrixCuda::is_valid() const { return rows_ > 0 && cols_ > 0 && !host_data_.empty(); } // 静态工厂方法 template CUDA_HOST MatrixCuda MatrixCuda::zeros(long rows, long cols) { MatrixCuda mat(rows, cols); mat.fill(T(0)); return mat; } template CUDA_HOST MatrixCuda MatrixCuda::ones(long rows, long cols) { MatrixCuda mat(rows, cols); mat.fill(T(1)); return mat; } template CUDA_HOST MatrixCuda MatrixCuda::identity(long size) { MatrixCuda mat(size, size); mat.fill(T(0)); for (long i = 0; i < size; ++i) { mat.set_element(i, i, T(1)); } return mat; } template CUDA_HOST MatrixCuda MatrixCuda::random(long rows, long cols, T min, T max) { MatrixCuda mat(rows, cols); mat.fill_random(min, max); return mat; } // 从现有Matrx类转换 template CUDA_HOST MatrixCuda MatrixCuda::from_matrx(const class Matrx& mat) { // 注意:这里假设Matrx类有get_row(), get_col(), get_data()方法 long rows = mat.get_row(); long cols = mat.get_col(); const std::vector& data = mat.get_data(); return MatrixCuda(rows, cols, data); } template CUDA_HOST class Matrx MatrixCuda::to_matrx() const { sync_device_to_host(); // 注意:这里假设Matrx类有相应的构造函数 // 实际实现可能需要根据Matrx类的具体接口调整 return class Matrx(rows_, cols_, host_data_); } // 私有辅助函数 template CUDA_HOST void MatrixCuda::check_index(long row, long col) const { if (row < 0 || row >= rows_ || col < 0 || col >= cols_) { throw std::out_of_range("Matrix index out of range"); } } template CUDA_HOST void MatrixCuda::initialize_from_vector(const std::vector& data) { if (data.size() != static_cast(rows_ * cols_)) { throw std::invalid_argument("Data size does not match matrix dimensions"); } host_data_ = data; host_modified_ = true; } // CUDA错误检查 template CUDA_HOST void MatrixCuda::check_cuda_error(cudaError_t error, const char* file, int line) { if (error != cudaSuccess) { std::cerr << "CUDA error at " << file << ":" << line << ": " << cudaGetErrorString(error) << std::endl; throw std::runtime_error("CUDA error occurred"); } } // 计算线程块和网格大小 template CUDA_HOST dim3 MatrixCuda::get_block_size(long total_elements) { // 使用256个线程的块(CUDA的典型值) const long max_threads_per_block = 256; long threads = std::min(total_elements, max_threads_per_block); return dim3(threads, 1, 1); } template CUDA_HOST dim3 MatrixCuda::get_grid_size(long total_elements, dim3 block_size) { // 计算需要的块数 long blocks = (total_elements + block_size.x - 1) / block_size.x; // 限制最大块数(避免过多块) const long max_blocks = 65535; blocks = std::min(blocks, max_blocks); return dim3(blocks, 1, 1); } // 显式实例化 template class MatrixCuda; template class MatrixCuda; } // namespace qing #endif // MATRIX_CUDA_INL_CUH