Skip to main content

跨文件引用代码的完整指南

在CUDA编程中,当你有多个.cu文件时,可以通过头文件(.h.cuh)来实现代码的共享和引用。下面是详细的实现方法。

1. 基本项目结构

project/
├── helper.cu # 包含需要共享的CUDA函数
├── helper.cuh # 声明helper.cu中的函数
├── main.cu # 主程序文件
└── Makefile # 编译脚本

2. 实现步骤

2.1. 创建头文件(.cuh

helper.cuh - 声明需要共享的函数和内核:

#ifndef HELPER_CUH
#define HELPER_CUH

#include <cuda_runtime.h>

// 声明设备函数(如果需要在多个文件中使用)
__device__ float device_helper_function(float x);

// 声明全局函数(内核)
__global__ void shared_kernel(float* input, float* output, int n);

// 声明主机辅助函数
void host_helper_function(float* data, int size);

// 声明CUDA内存管理函数
cudaError_t allocate_memory(float** ptr, size_t size);
cudaError_t free_memory(float* ptr);

#endif // HELPER_CUH

2.2. 实现源文件(.cu

helper.cu - 实现头文件中声明的函数:

#include "helper.cuh"
#include <stdio.h>

// 实现设备函数
__device__ float device_helper_function(float x) {
return x * x + 2.0f * x + 1.0f;
}

// 实现全局函数(内核)
__global__ void shared_kernel(float* input, float* output, int n) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < n) {
output[idx] = device_helper_function(input[idx]);
}
}

// 实现主机辅助函数
void host_helper_function(float* data, int size) {
printf("Processing %d elements in helper function\n", size);
// 这里可以添加更多的处理逻辑
}

// 实现内存分配函数
cudaError_t allocate_memory(float** ptr, size_t size) {
return cudaMalloc(ptr, size);
}

cudaError_t free_memory(float* ptr) {
return cudaFree(ptr);
}

2.3. 主程序文件(.cu

main.cu - 引用并使用另一个文件中的代码:

#include "helper.cuh"  // 包含共享的头文件
#include <iostream>
#include <cuda_runtime.h>

// 错误检查宏
#define CHECK_CUDA_ERROR(call) \
{ \
cudaError_t err = call; \
if (err != cudaSuccess) { \
std::cerr << "CUDA error at " << __FILE__ << ":" << __LINE__ \
<< " - " << cudaGetErrorString(err) << std::endl; \
exit(1); \
} \
}

int main() {
const int n = 1000;
size_t size = n * sizeof(float);

// 使用helper.cu中的函数分配内存
float *d_input, *d_output;
CHECK_CUDA_ERROR(allocate_memory(&d_input, size));
CHECK_CUDA_ERROR(allocate_memory(&d_output, size));

// 使用helper.cu中的主机函数
host_helper_function(nullptr, n);

// 配置内核启动参数
int blockSize = 256;
int gridSize = (n + blockSize - 1) / blockSize;

// 调用helper.cu中定义的内核
shared_kernel<<<gridSize, blockSize>>>(d_input, d_output, n);

// 检查内核执行错误
CHECK_CUDA_ERROR(cudaGetLastError());
CHECK_CUDA_ERROR(cudaDeviceSynchronize());

std::cout << "Kernel executed successfully!" << std::endl;

// 清理
CHECK_CUDA_ERROR(free_memory(d_input));
CHECK_CUDA_ERROR(free_memory(d_output));

return 0;
}

3. 编译方法

3.1. 使用NVCC直接编译

# 【方法一】编译所有.cu文件并链接
nvcc -o my_program main.cu helper.cu

# 【方法二】分步编译
nvcc -c helper.cu -o helper.o
nvcc -c main.cu -o main.o
nvcc main.o helper.o -o my_program

3.2. 使用Makefile

Makefile:

# 编译器设置
NVCC = nvcc
NVCC_FLAGS = -O3
TARGET = my_program

# 源文件
SOURCES = main.cu helper.cu
OBJECTS = $(SOURCES:.cu=.o)

# 默认目标
all: $(TARGET)

# 链接目标文件
$(TARGET): $(OBJECTS)
$(NVCC) $(NVCC_FLAGS) $(OBJECTS) -o $(TARGET)

# 编译.cu文件到.o文件
%.o: %.cu
$(NVCC) $(NVCC_FLAGS) -c $< -o $@

# 清理
clean:
rm -f $(TARGET) $(OBJECTS)

# 重新编译
rebuild: clean all

编译和运行:

# 编译项目
make

# 运行程序
./my_program
Processing 1000 elements in helper function
Kernel executed successfully!

3.3. 使用CMake编译

# 设置CMake最低版本要求
cmake_minimum_required(VERSION 3.18 FATAL_ERROR)

# 设置项目名称和版本
project(my_program
VERSION 1.0
DESCRIPTION "A simple CUDA project with CMake"
LANGUAGES CXX CUDA) # 注意:这里必须包含CUDA语言

# 设置C++标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 设置CUDA架构(根据你的GPU调整)
set(CUDA_ARCH "80" CACHE STRING "CUDA architecture")
set(CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH})

# 打印配置信息
message(STATUS "Building for CUDA architecture: ${CUDA_ARCH}")

# 添加包含目录
include_directories(./)

# 查找CUDA工具包(现代CMake版本通常不需要显式调用,但为了兼容性保留)
find_package(CUDAToolkit REQUIRED)

# 添加可执行文件
add_executable(${PROJECT_NAME}
main.cu
helper.cu
)

# 设置CUDA编译选项
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<COMPILE_LANGUAGE:CUDA>:
-Xcompiler=-Wall
-Xcompiler=-Wextra
--default-stream per-thread
>
)

# 设置目标属性
set_target_properties(${PROJECT_NAME} PROPERTIES
CUDA_SEPARABLE_COMPILATION ON
CUDA_RESOLVE_DEVICE_SYMBOLS ON
)

# 链接CUDA运行时库(现代CMake会自动处理,但显式声明更清晰)
target_link_libraries(${PROJECT_NAME} PRIVATE
CUDA::cudart
)

# 安装规则(可选)
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin
)

# 添加测试(可选)
enable_testing()
add_test(NAME run_cuda_example
COMMAND ${PROJECT_NAME}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)