【问题标题】:maximum supported size for cub librarycub 库支持的最大大小
【发布时间】:2016-01-07 01:29:59
【问题描述】:

有谁知道 cub::scan 支持的最大尺寸是多少?我得到了超过 5 亿输入大小的核心转储。我想确保我没有做错任何事......

这是我的代码:

#define CUB_STDERR
#include <stdio.h>
#include "cub/util_allocator.cuh"
#include "cub/device/device_scan.cuh"
#include <sys/time.h>
using namespace cub;

bool                    g_verbose = false;  // Whether to display input/output to console
CachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory
typedef int mytype;

/**
 * Solve inclusive-scan problem
 */

static void solve(mytype *h_in, mytype *h_cpu, int n)
{
    mytype inclusive = 0;
    for (int i = 0; i < n; ++i) {
      inclusive += h_in[i];
      h_cpu[i] = inclusive;
    }
}
static int compare(mytype *h_cpu, mytype *h_o, int n)
{
    for (int i = 0; i < n; i++) {
      if (h_cpu[i] != h_o[i]) {
        return i + 1;
      }
    }
    return 0;
}

/**
 * Main
 */
int main(int argc, char** argv)
{
    cudaSetDevice(0);
    struct timeval start, end;
    int num_items = 1073741824;
    const int repetitions = 5;
    mytype *h_in, *h_out, *h_cpu;
    const int size = num_items * sizeof(mytype);
    // Allocate host arrays
    h_in = (mytype *)malloc(size);
    h_out = (mytype *)malloc(size);
    h_cpu = (mytype *)malloc(size);


    // Initialize problem and solution
    for (int i = 0; i < num_items; i++) {
        h_in[i] = i;
        h_out[i] = 0;
        h_cpu[i] = 0;
    }

    solve(h_in, h_cpu, num_items);

    // Allocate problem device arrays
    mytype *d_in = NULL;
    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(mytype) * num_items));

    // Initialize device input
    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(mytype) * num_items, cudaMemcpyHostToDevice));

    // Allocate device output array
    mytype *d_out = NULL;
    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(mytype) * num_items));

    // Allocate temporary storage
    void            *d_temp_storage = NULL;
    size_t          temp_storage_bytes = 0;


    CubDebugExit(DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items));
    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));

    // Run
    gettimeofday(&start, NULL);
    for (long i = 0; i < repetitions; i++) 
        DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items);
    cudaThreadSynchronize();
    gettimeofday(&end, NULL);
    double ctime = end.tv_sec + end.tv_usec / 1000000.0 - start.tv_sec - start.tv_usec / 1000000.0;

    cudaMemcpy(h_out, d_out, sizeof(mytype) * num_items, cudaMemcpyDeviceToHost);
    int cmp = compare(h_cpu, h_out, num_items);
    printf("%d\t", num_items);
    if (!cmp)
        printf("\t%7.4fs \n", ctime);
    printf("\n");
    if (h_in) delete[] h_in;
    if (h_out) delete[] h_out;
    if (h_cpu) delete[] h_cpu;
    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));
    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));
    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));

    printf("\n\n");

    return 0;
}

【问题讨论】:

  • 您使用的是什么 GPU,它有多少内存?另外,您正在对什么类型执行扫描?
  • 我正在使用 TitanX,它有 12GB。我正在执行独占设备扫描。
  • 您对什么数据类型执行扫描? int, float, double, ... ?你有多少主机内存?
  • Here 是在大小为 1073741824(超过 10 亿个元素)的 int 数组上的 cub::ExclusiveSum 的工作示例。它是在具有 64GB 主机内存和 K40c(也有 12GB)的 RHEL 6.2 系统上使用 CUDA 7.0 和 CUB 1.4.1 完成的。最终,如果您没有遇到内存分配错误,那么 cub 应该能够处理最多适合 int num_items 变量的最大正数 - 大约 20 亿个元素。但是在达到这个数字之前,内存限制可能会发挥作用,特别是取决于您使用的数据类型。
  • 我正在处理 32 位整数,它适用于 268435456 个元素,但在此之上我得到分段错误(核心转储)。对于 64 位整数,它仅适用于 134217728 个整数,并且对于高于此的任何内容,我都会得到相同的错误。我正在使用 CubDebugExit 进行分配设备输入/输出,所以如果它与内存分配有关,我必须得到更有意义的错误消息吗?

标签: cuda nvidia cub prefix-sum


【解决方案1】:

问题出在这里:

const int size = num_items * sizeof(mytype);

并且可以通过将其更改为:

const size_t size = num_items * sizeof(mytype);

代码中num_items的值超过10亿。当我们将它乘以sizeof(mytype) 时,我们将它乘以 4,所以结果超过了 40 亿。此值不能存储在int 变量中。如果您尝试像那样使用它,那么您的后续主机代码将做坏事。这个问题(核心转储)实际上与 CUDA 无关。如果您删除了所有 CUB 元素,代码将转储核心。

当我修改上面的代码行并针对正确的 GPU 进行编译时(例如,-arch=sm_35 在我的情况下,或 -arch=sm_52 用于 Titan X GPU),然后我得到正确的答案(并且没有 seg 错误/核心转储)。

一般来说,追查 seg 故障/核心转储类型错误的正确起点是认识到此错误是由主机代码引起的,并且您应该尝试本地化源代码的确切行那就是产生这个错误。这可以通过在您的代码中放置许多 printf 语句来简单/繁琐地完成,直到您识别出您看不到任何 printf 输出的代码行,或者使用主机代码调试器,例如 linux 上的 gdb .

另请注意,编写的此代码在主机上需要略多于 12GB 的内存,在 GPU 上需要略多于 8GB 的​​内存,因此它只能在这样的设置下正常运行。

作为参考,这里是固定代码(基于 OP 发布的here):

#define CUB_STDERR
#include <stdio.h>
#include "cub/util_allocator.cuh"
#include "cub/device/device_scan.cuh"
#include <sys/time.h>
using namespace cub;

bool                    g_verbose = false;  // Whether to display input/output to console
CachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory
typedef int mytype;

/**
 * Solve inclusive-scan problem
 */

static void solve(mytype *h_in, mytype *h_cpu, int n)
{
    mytype inclusive = 0;
    for (int i = 0; i < n; ++i) {
      inclusive += h_in[i];
      h_cpu[i] = inclusive;
    }
}
static int compare(mytype *h_cpu, mytype *h_o, int n)
{
    for (int i = 0; i < n; i++) {
      if (h_cpu[i] != h_o[i]) {
        return i + 1;
      }
    }
    return 0;
}

/**
 * Main
 */
int main(int argc, char** argv)
{
    cudaSetDevice(0);
    struct timeval start, end;
    int num_items = 1073741824;
    const int repetitions = 5;
    mytype *h_in, *h_out, *h_cpu;
    const size_t size = num_items * sizeof(mytype);
    // Allocate host arrays
    h_in = (mytype *)malloc(size);
    h_out = (mytype *)malloc(size);
    h_cpu = (mytype *)malloc(size);


    // Initialize problem and solution
    for (int i = 0; i < num_items; i++) {
        h_in[i] = i;
        h_out[i] = 0;
        h_cpu[i] = 0;
    }

    solve(h_in, h_cpu, num_items);

    // Allocate problem device arrays
    mytype *d_in = NULL;
    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(mytype) * num_items));

    // Initialize device input
    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(mytype) * num_items, cudaMemcpyHostToDevice));

    // Allocate device output array
    mytype *d_out = NULL;
    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(mytype) * num_items));

    // Allocate temporary storage
    void            *d_temp_storage = NULL;
    size_t          temp_storage_bytes = 0;


    CubDebugExit(DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items));
    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));

    // Run
    gettimeofday(&start, NULL);
    for (long i = 0; i < repetitions; i++) 
        DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items);
    cudaThreadSynchronize();
    gettimeofday(&end, NULL);
    double ctime = end.tv_sec + end.tv_usec / 1000000.0 - start.tv_sec - start.tv_usec / 1000000.0;

    cudaMemcpy(h_out, d_out, sizeof(mytype) * num_items, cudaMemcpyDeviceToHost);
    int cmp = compare(h_cpu, h_out, num_items);
    printf("%d\t", num_items);
    if (!cmp)
        printf("\t%7.4fs \n", ctime);
    printf("\n");
    if (h_in) delete[] h_in;
    if (h_out) delete[] h_out;
    if (h_cpu) delete[] h_cpu;
    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));
    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));
    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));

    printf("\n\n");

    return 0;
}

【讨论】:

    猜你喜欢
    • 2014-01-27
    • 2019-04-14
    • 1970-01-01
    • 2013-05-24
    • 2013-08-07
    • 2021-10-10
    • 2011-02-11
    • 2016-12-16
    • 2014-07-18
    相关资源
    最近更新 更多