You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++中拼接std::thread多线程生成的LibTorch张量

问题分析

你的核心问题是线程执行的异步性:直接在创建线程后拼接,此时线程可能还未完成函数调用,对应位置的张量未生成;或是多线程无同步地修改共享结果容器,引发内存竞争错误。正确思路是先让所有线程完成任务并将结果存入对应索引的容器,再统一按顺序拼接。

正确实现步骤
  1. 预分配结果容器:根据调用次数创建固定大小的容器,每个位置对应一个线程的返回张量。
  2. 线程绑定索引:每个线程执行函数后,将结果存入容器的指定索引位置(若每个线程仅操作独立索引,无需加锁;涉及共享资源时需用互斥量保护)。
  3. 等待所有线程完成:调用std::thread::join()确保所有线程执行完毕,避免访问未初始化的结果。
  4. 按索引顺序拼接所有张量为大张量。
代码示例

原尝试错误代码(常见问题)

#include <thread>
#include <vector>
#include <Eigen/Dense> // 假设使用Eigen张量库

Eigen::RowVectorXd generate_tensor() {
    Eigen::RowVectorXd tensor(8);
    tensor.setRandom(); // 模拟生成张量逻辑
    return tensor;
}

int main() {
    const int call_times = 12;
    Eigen::MatrixXd result(0, 8);

    std::vector<std::thread> threads;
    for (int i = 0; i < call_times; ++i) {
        threads.emplace_back([&]() {
            auto tensor = generate_tensor();
            // 错误:多线程同时修改result会引发数据竞争
            result.conservativeResize(result.rows() + 1, Eigen::NoChange);
            result.row(result.rows() - 1) = tensor;
        });
        // 错误:未等待线程完成就继续循环,后续拼接会访问未初始化内存
    }

    // 未调用join,程序退出时线程可能仍在运行
    return 0;
}

正确实现代码

#include <thread>
#include <vector>
#include <Eigen/Dense>

// 生成1×8张量的函数
Eigen::RowVectorXd generate_tensor() {
    Eigen::RowVectorXd tensor(8);
    tensor.setRandom(); // 模拟生成逻辑
    return tensor;
}

int main() {
    const int call_times = 12;
    // 预分配结果容器,每个位置对应一个线程的结果
    std::vector<Eigen::RowVectorXd> results(call_times);

    std::vector<std::thread> threads;
    for (int i = 0; i < call_times; ++i) {
        // 按值捕获索引i,避免闭包引用共享变量导致的索引混乱
        threads.emplace_back([i, &results]() {
            results[i] = generate_tensor();
            // 每个线程仅写入自己的索引位置,无数据竞争,无需加锁
        });
    }

    // 等待所有线程执行完毕
    for (auto& t : threads) {
        t.join();
    }

    // 拼接所有张量为12×8的大张量
    Eigen::MatrixXd final_result(call_times, 8);
    for (int i = 0; i < call_times; ++i) {
        final_result.row(i) = results[i];
    }

    // 输出验证(可选)
    std::cout << final_result << std::endl;
    return 0;
}
CMakeLists.txt配置

需要链接线程库(Linux下为pthread),若使用Eigen则引入对应库:

cmake_minimum_required(VERSION 3.10)
project(tensor_thread_demo)

set(CMAKE_CXX_STANDARD 17)

# 寻找Eigen库(使用自定义张量可移除此段)
find_package(Eigen3 REQUIRED)

add_executable(tensor_thread_demo main.cpp)

# 链接依赖库
target_link_libraries(tensor_thread_demo PRIVATE Eigen3::Eigen)
# Linux下需链接pthread,Windows无需
if(UNIX)
    target_link_libraries(tensor_thread_demo PRIVATE pthread)
endif()
关键注意点
  • 闭包索引捕获:必须按值捕获i,否则所有线程会共享同一个i的引用,导致结果存入错误索引。
  • 线程同步:必须调用join()等待所有线程完成,否则结果容器可能存在未初始化的张量。
  • 无锁条件:当每个线程仅写入容器的独立索引位置时,无需加锁;若涉及全局共享资源,则需要用std::mutex保护访问。

内容的提问来源于stack exchange,提问作者Ant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:33:28