配置条件:win11, GPU 12.6,cuda 12.6.3, cudnn 8.9.7, vs 2022, libtorch 2.9.0, Release模式

注意:cuda、 cudnn、libtorch、vs这几个一定要匹配,否则可能会报错。他们很矫情~~

cmakelists.txt设置如下

cmake_minimum_required(VERSION 3.28)
project(libtorchtest)

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

# 设置构建目录为输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})


# LibTorch 配置
set(CMAKE_PREFIX_PATH "G:/software/libtorch290_cu126Release")
find_package(Torch REQUIRED)

if(NOT Torch_FOUND)
    message(FATAL_ERROR "LibTorch not found")
endif()

message(STATUS "Torch include directories: ${TORCH_INCLUDE_DIRS}")
message(STATUS "Torch libraries: ${TORCH_LIBRARIES}")

# 包含头文件目录
include_directories(${TORCH_INCLUDE_DIRS})

# 一次性复制所有必需的 DLL 文件
add_custom_target(copy_dlls ALL
        COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "G:/software/libtorch290_cu126Release/lib/torch_cpu.dll"
        ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "G:/software/libtorch290_cu126Release/lib/torch_cuda.dll"
        ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "G:/software/libtorch290_cu126Release/lib/c10.dll"
        ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "G:/software/libtorch290_cu126Release/lib/c10_cuda.dll"
        ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "G:/software/libtorch290_cu126Release/lib/libiomp5md.dll"    
        ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
        COMMENT "Copying DLL files to build directory"
)

#[[  第一种写法
 函数:添加 Torch 可执行文件
function(add_torch_executable target_name source_file)
    add_executable(${target_name} ${source_file})
    target_link_libraries(${target_name} ${TORCH_LIBRARIES})
    add_dependencies(${target_name} copy_dlls)

    # 设置目标属性,确保包含目录正确
    target_include_directories(${target_name} PRIVATE ${TORCH_INCLUDE_DIRS})

    # Windows 特定设置
    if(WIN32)
        target_compile_definitions(${target_name} PRIVATE _USE_MATH_DEFINES)
        target_link_options(${target_name} PRIVATE "/INCLUDE:?warp_size@cuda@at@@YAHXZ")
    endif()
endfunction()
# 添加所有可执行文件
#add_torch_executable(SVM      ../SVM.cpp)
#add_torch_executable(LinearRegression ../LinearRegression.cpp)
#add_torch_executable(LSTMM      ../LSTMM.cpp)
#add_torch_executable(test     ../test.cpp)
#]]

# 以下是第二种写法
add_executable(test ../test.cpp)
if(MSVC)
    # 禁用 C4267 警告
    add_compile_options(/wd4267)
    # 或者针对特定目标
    target_compile_options(test PRIVATE /wd4267)
endif()
target_link_libraries(test ${TORCH_LIBRARIES})
add_dependencies(test copy_dlls)
# 设置目标属性,确保包含目录正确
target_include_directories(test PRIVATE ${TORCH_INCLUDE_DIRS})

#[[ Windows 特定设置
if(WIN32)
    target_compile_definitions(test PRIVATE _USE_MATH_DEFINES)
    target_link_options(test PRIVATE "/INCLUDE:?warp_size@cuda@at@@YAHXZ")
endif()  #]]

add_executable(LSTMM ../LSTMM.cpp)
target_link_libraries(LSTMM ${TORCH_LIBRARIES})
add_dependencies(LSTMM copy_dlls)
# 设置目标属性,确保包含目录正确
target_include_directories(LSTMM PRIVATE ${TORCH_INCLUDE_DIRS})

测试代码(循环神经网络LSTM)

#include <torch/torch.h>
#include <iostream>
#include <vector>

// 定义 LSTM 模型
struct LSTMNet : torch::nn::Module {
    LSTMNet(int input_size, int hidden_size, int num_layers, int output_size) {
        // 使用成员函数设置LSTM选项
        auto lstm_options = torch::nn::LSTMOptions(input_size, hidden_size)
                .num_layers(num_layers)
                .batch_first(true);

        // 注册模块
        lstm = register_module("lstm", torch::nn::LSTM(lstm_options));
        fc = register_module("fc", torch::nn::Linear(hidden_size, output_size));
    }

    torch::Tensor forward(torch::Tensor x) {
        // 获取LSTM参数
        int64_t num_layers = lstm->options.num_layers();
        int64_t hidden_size = lstm->options.hidden_size();

        // 初始化隐藏状态
        auto h0 = torch::zeros({num_layers, x.size(0), hidden_size}).to(x.device());
        auto c0 = torch::zeros({num_layers, x.size(0), hidden_size}).to(x.device());

        // LSTM 前向传播
        auto lstm_out = lstm->forward(x, std::make_tuple(h0, c0));
        auto out = std::get<0>(lstm_out);

        // 只取最后一个时间步的输出
        auto out_last = out.index({torch::indexing::Slice(), -1});

        // 全连接层
        return fc->forward(out_last);
    }

    torch::nn::LSTM lstm{nullptr};
    torch::nn::Linear fc{nullptr};
};

int main() {
    // 1. 设置设备 (优先使用GPU)
    torch::Device device = torch::cuda::is_available() ?
                           torch::Device(torch::kCUDA) :
                           torch::Device(torch::kCPU);
    std::cout << "Using device: " << device << std::endl;

    // 2. 超参数设置
    const int sequence_length = 10;  // 序列长度
    const int input_size = 1;        // 输入特征维度
    const int hidden_size = 64;      // LSTM隐藏层大小
    const int num_layers = 2;        // LSTM层数
    const int output_size = 1;       // 输出维度
    const int batch_size = 32;       // 批大小
    const int num_epochs = 100;      // 训练轮数
    const float learning_rate = 0.01;

    // 3. 创建模型并移至GPU
    auto model = std::make_shared<LSTMNet>(input_size, hidden_size, num_layers, output_size);
    model->to(device);

    // 4. 创建优化器和损失函数
    torch::optim::Adam optimizer(model->parameters(), torch::optim::AdamOptions(learning_rate));
    auto criterion = torch::nn::MSELoss();

    // 5. 生成模拟数据 (正弦波序列)
    std::vector<float> data;
    for (int i = 0; i < 1000; ++i) {
        data.push_back(std::sin(i * 0.1));
    }

    // 6. 创建数据集
    auto dataset = torch::from_blob(data.data(), {static_cast<int64_t>(data.size())})
            .to(torch::kFloat32)
            .view({-1, 1});

    // 7. 训练循环
    std::cout << "Start training..." << std::endl;
    for (int epoch = 0; epoch < num_epochs; ++epoch) {
        float epoch_loss = 0;
        int batch_count = 0;

        // 迭代批次
        for (int i = 0; i < data.size() - sequence_length - batch_size; i += batch_size) {
            // 准备输入和目标张量
            std::vector<torch::Tensor> inputs, targets;
            for (int j = 0; j < batch_size; ++j) {
                int start_idx = i + j;
                auto input_seq = dataset.index({torch::indexing::Slice(start_idx, start_idx + sequence_length)});
                auto target_val = dataset.index({start_idx + sequence_length});

                inputs.push_back(input_seq);
                targets.push_back(target_val);
            }

            // 创建批次张量 [batch_size, seq_len, input_size]
            auto batch_input = torch::stack(inputs).view({batch_size, sequence_length, input_size});
            auto batch_target = torch::stack(targets).view({batch_size, output_size});

            // 移至设备
            batch_input = batch_input.to(device);
            batch_target = batch_target.to(device);

            // 前向传播
            auto output = model->forward(batch_input);

            // 计算损失
            auto loss = criterion(output, batch_target);
            epoch_loss += loss.item<float>();
            batch_count++;

            // 反向传播和优化
            optimizer.zero_grad();
            loss.backward();
            optimizer.step();
        }

        // 打印训练进度
        if ((epoch + 1) % 10 == 0) {
            std::cout << "Epoch [" << (epoch + 1) << "/" << num_epochs
                      << "], Loss: " << (epoch_loss / batch_count) << std::endl;
        }
    }

    // 8. 模型测试
    std::cout << "\nTesting model..." << std::endl;
    model->eval();  // 设置为评估模式

    // 使用最后一段序列进行预测
    auto test_input = dataset.index({
                                            torch::indexing::Slice(dataset.size(0) - sequence_length, torch::indexing::None)
                                    }).view({1, sequence_length, input_size}).to(device);

    auto prediction = model->forward(test_input);

    // 打印实际值和预测值
    float actual_value = dataset[dataset.size(0) - 1].item<float>();
    float predicted_value = prediction.item<float>();

    std::cout << "Actual next value: " << actual_value << std::endl;
    std::cout << "Predicted next value: " << predicted_value << std::endl;
    std::cout << "Absolute error: " << std::abs(actual_value - predicted_value) << std::endl;

    return 0;
}

运行结果

Using device: cuda
Start training...
Epoch [10/100], Loss: 2.66655e-06
Epoch [20/100], Loss: 0.000258789
Epoch [30/100], Loss: 0.000613829
Epoch [40/100], Loss: 4.297e-06
Epoch [50/100], Loss: 0.00117912
Epoch [60/100], Loss: 1.13044e-07
Epoch [70/100], Loss: 0.00135332
Epoch [80/100], Loss: 2.26288e-05
Epoch [90/100], Loss: 1.03347e-07
Epoch [100/100], Loss: 2.108e-06

Testing model...
Actual next value: -0.589924
Predicted next value: -0.503256
Absolute error: 0.0866677

Process finished with exit code 0

更多推荐