幼崽分割的还原未产生结果



我正在尝试使用幼崽的分段还原和原始的总和。

这是我的代码:

int main() {

     const int N = 7;
     const int num_segments  = 3;
     int d_offsets[]= {0,3,3,7};

    int *h_data       = (int *)malloc(N * sizeof(int));
    int *h_result = (int *)malloc(num_segments * sizeof(int));

    for (int i=0; i<N; i++) {
        h_data[i] = 3;
    }

    int *d_data;
    cudaMalloc((int**)&d_data, N * sizeof(int));
    cudaMemcpy(d_data, h_data, N * sizeof(int), cudaMemcpyHostToDevice);

    int           *d_result;
    cudaMalloc((int**)&d_result, num_segments * sizeof(int));
    void            *d_temp_storage = NULL;
    size_t          temp_storage_bytes = 0;

    cudaMalloc((void**)&d_temp_storage, temp_storage_bytes);

    cub::DeviceSegmentedReduce::Sum(d_temp_storage, temp_storage_bytes, d_data, d_result,
        num_segments, d_offsets, d_offsets + 1);

    cudaMemcpy(h_result, d_result, num_segments*sizeof(int), cudaMemcpyDeviceToHost);


    printf("Results:n");
   for (int i=0; i<num_segments; i++) {
        printf("CUB: %dn", h_result[i]);
    }

}

,但结果我得到了:

Results:
CUB: 0
CUB: 0
CUB: 0

我无法确定问题到底是什么。在真实的示例中,我有一个非常大的阵列,段等于400。s我可以优化代码,以使我不需要声明并为d_offsets分配内存。

您真的没有认真尝试调试代码:

  • 您缺少d_results的内存分配(您修复了(
  • 您正在尝试通过d_offsets中的设备内存地址传递主机存储器地址。当然,这会导致CUDA运行时错误 - 但
  • 您没有检查运行时错误。
  • 您仅调用一次Cub功能 - 尽管您必须将其运行两次才能实际做任何事情:以nullptr作为划痕空间,以获取刮擦空间大小,然后再次使用实际的划痕空间进行工作。这是一个令人讨厌的API,但这就是它的工作方式。

当您没有花时间做自己时,您不适合浪费SO社区的时间来调试您的代码。

仍然,您可以做一些事情避免必须检查错误,至少是使用某种形式的库来为您服务(例如,通过抛出错误(。如果您这样做 - 例如,使用我的CUDA运行时API包装器(对不起,自插头(,并适当地分配了您所需的所有内容,您最终会得到类似的东西:

#include <cub/cub.cuh>
#include <cuda/api_wrappers.h>
#include <vector>
#include <cstdlib>
int main() {
    const int N = 7;
    const int num_segments  = 3;
    auto h_offsets = std::vector<int> {0,3,3,7};
    auto h_data = std::vector<int>(N);
    auto h_results = std::vector<int>(num_segments);
    std::fill(h_data.begin(), h_data.end(), 3);
    auto current_device = cuda::device::current::get();
    auto d_offsets = cuda::memory::device::make_unique<int[]>(
        current_device, h_offsets.size());
    auto d_data = cuda::memory::device::make_unique<int[]>(
        current_device, N);
    cuda::memory::copy(
        d_offsets.get(), &h_offsets[0], h_offsets.size() * sizeof(int));
    cuda::memory::copy(
        d_data.get(),  &h_data[0], h_data.size() * sizeof(int));
    auto d_results = cuda::memory::device::make_unique<int[]>(
        current_device, num_segments);
    auto d_start_offsets = d_offsets.get();
    auto d_end_offsets = d_start_offsets + 1; // aliasing, see CUB documentation
    size_t temp_storage_bytes = 0;
    // This call merely obtains a value for temp_storage_bytes, passed here
    // as a non-const reference; other arguments are unused
    cub::DeviceSegmentedReduce::Sum(
        nullptr, temp_storage_bytes, d_data.get(), d_results.get(),
        num_segments, d_start_offsets, d_end_offsets);
    auto d_temp_storage = cuda::memory::device::make_unique<char[]>(
        current_device, temp_storage_bytes);
    cub::DeviceSegmentedReduce::Sum(
        d_temp_storage.get(), temp_storage_bytes, d_data.get(), 
        d_results.get(), num_segments, d_start_offsets, d_end_offsets);
    cuda::memory::copy(
        &h_results[0], d_results.get(), num_segments * sizeof(int));
    std::cout << "Results:n";
    for (int i=0; i<num_segments; i++) {
        std::cout << "Segment " << i << " data sums up to " << h_results[i] << "n";
    }
    return EXIT_SUCCESS;
}

有效的工作:

Results:
Segment 0 data sums up to 9
Segment 1 data sums up to 0
Segment 2 data sums up to 12

其他提示:

  • 始终调查编译器警告。
  • 使用 cuda-memcheck避免内存泄漏/在错误的设备/主机侧等初始化
  • 如果您直接使用CUDA运行时API,则您必须必须检查所有错误的电话。

最新更新