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

thrust::reduce设备代码迭代范围受限问题及矩阵内维归约咨询

问题解答

1. 错误与线程块最大线程数的关系

直接原因并非RTX3080Ti的线程块最大1024线程数限制,而是你在thrust::transform的设备端lambda中嵌套调用thrust::reduce(thrust::device,...)的实现方式存在问题:

  • 这种写法会让每个transform线程独立启动一个reduce CUDA核,当N=2048时,会同时触发2048个reduce核执行。每个reduce核处理大尺寸M的元素时,需要分配临时缓冲区用于中间归约计算,大量并发的内存分配请求会耗尽设备临时内存,从而触发temporary_buffer::allocate失败,最终导致核启动报错。
  • 线程块1024的限制是硬件规格,但Thrust的reduce实现会自动适配该限制(比如通过多轮归约处理超过1024的元素),因此不是报错的直接诱因。

2. 矩阵沿内维归约的标准实现方法

推荐使用Thrust原生的分段归约或**reduce_by_key**实现,避免嵌套核启动的问题,同时保证计算效率:

方法一:利用thrust::reduce_by_key

通过构造键值对,将同一行的元素标记为相同键,对相同键的元素执行归约:

#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/fill.h>
#include <thrust/reduce.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/functional.h>

constexpr unsigned int N = 2048, M = 4096; // 支持更大的M值

int main(int argc, char* argv[]) {
    thrust::device_vector<double> g_vec1(N*M);
    thrust::device_vector<double> g_vec2(N);
    thrust::fill(thrust::device, g_vec1.begin(), g_vec1.end(), 1.);

    // 构造键迭代器:每M个元素对应同一个行索引(0到N-1)
    auto keys_begin = thrust::make_transform_iterator(
        thrust::counting_iterator<int>(0),
        [M](int idx) { return idx / M; }
    );

    // 对相同键的元素求和,输出每行的归约结果
    thrust::reduce_by_key(
        keys_begin, keys_begin + N*M,
        g_vec1.begin(),
        thrust::make_discard_iterator(), // 无需输出键
        g_vec2.begin(),
        thrust::equal_to<int>(),
        thrust::plus<double>()
    );

    return 0;
}

方法二:利用thrust::segmented_reduce

构造分段起始标记迭代器,直接对每个分段(行)执行归约:

#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/fill.h>
#include <thrust/segmented_reduce.h>
#include <thrust/iterator/counting_iterator.h>

constexpr unsigned int N = 2048, M = 4096;

int main(int argc, char* argv[]) {
    thrust::device_vector<double> g_vec1(N*M);
    thrust::device_vector<double> g_vec2(N);
    thrust::fill(thrust::device, g_vec1.begin(), g_vec1.end(), 1.);

    // 构造分段标记:每行第一个元素标记为true,其余为false
    auto flags_begin = thrust::make_transform_iterator(
        thrust::counting_iterator<int>(0),
        [M](int idx) { return (idx % M) == 0; }
    );

    // 执行分段归约,输出每行的求和结果
    thrust::segmented_reduce(
        thrust::device,
        g_vec1.begin(), g_vec1.end(),
        flags_begin,
        g_vec2.begin(),
        thrust::plus<double>()
    );

    return 0;
}

这两种方法均通过单次核调用完成所有行的归约,内存使用更高效,能支持更大的M值,完全符合Thrust的标准使用范式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:25:35