Мультипроцессорные пакетные 1D БПФ: кажется, что работает только один графический процессор - PullRequest
0 голосов
/ 09 января 2020

У меня есть три Tesla V100 на RHEL 8 с инструментарием CUDA версии 10.2.89.

Я пытаюсь вычислить пакет 1-мерных БПФ столбцов основной матрицы строки. В приведенном ниже примере матрица имеет размер 16x8, поэтому при использовании трех графических процессоров я ожидаю, что графический процессор 0 будет выполнять БПФ первых трех столбцов, графический процессор 1 будет выполнять БПФ следующих 3, а графический процессор 2 будет выполнять БПФ последних 2 .

План, созданный в примере, работает должным образом на одном графическом процессоре, но при работе на трех вычисляются только первые три столбца (правильно), остальные не затрагиваются.

Когда я Осмотрите дескриптор, который заполнен cufftXtMallo c, я вижу, что он выделил место для 123 элементов на GPU 0 и 1 и 122 на GPU 2. Это кажется странным: я ожидал бы 48 = 16 * 3 на GPU 0 и 1 и 32 = 16 * 2 на GPU 2. Действительно, это размер рабочих пространств, заполненных cufftMakePlanMany. Когда я проверяю данные, которые были скопированы, элементы 0-122 находятся в буфере на GPU 0, а элементы 123-127 находятся в начале буфера на GPU 1. Остальная часть этого буфера и буфер на GPU 2 являются ненужными .

Кроме того, когда я увеличиваю количество строк до 1024, я получаю SIGABRT на вызов cufftXtFree с сообщением «free (): поврежденные несортированные чанки».

#include "cufft.h"
#include "cufftXt.h"
#include <vector>
#include <cuComplex.h>
#include <cassert>

#define CUDA_CHECK(x) assert(x == cudaSuccess)
#define CUFFT_CHECK(x) assert(x == CUFFT_SUCCESS)

int main() {
    static const int numGPUs = 3;
    int gpus[numGPUs] = {0, 1, 2};

    int nr = 16;
    int nc = 8;

    // Fill with junk data
    std::vector<cuFloatComplex> h_x(nr * nc);
    for (int i = 0; i < nr * nc; ++i) {
        h_x[i].x = static_cast<float>(i);
    }

    cufftHandle plan;
    CUFFT_CHECK(cufftCreate(&plan));
    CUFFT_CHECK(cufftXtSetGPUs(plan, numGPUs, gpus));

    std::vector<size_t> workSizes(numGPUs);
    int n[] = {nr};

    CUFFT_CHECK(cufftMakePlanMany(plan,
                                  1, // rank
                                  n, // n
                                  n, // inembed
                                  nc, // istride
                                  1, // idist
                                  n, // onembed
                                  nc, // ostride
                                  1, // odist
                                  CUFFT_C2C,
                                  nc,
                                  workSizes.data()));

    cudaLibXtDesc *d_x;
    CUFFT_CHECK(cufftXtMalloc(plan, &d_x, CUFFT_XT_FORMAT_INPLACE));

    CUFFT_CHECK(cufftXtMemcpy(plan, d_x, (void *)h_x.data(), CUFFT_COPY_HOST_TO_DEVICE));

    CUFFT_CHECK(cufftXtExecDescriptorC2C(plan, d_x, d_x, CUFFT_FORWARD));

    std::vector<cuFloatComplex> h_out(nr * nc);
    CUFFT_CHECK(cufftXtMemcpy(plan, (void *)h_out.data(), d_x, CUFFT_COPY_DEVICE_TO_HOST));

    CUFFT_CHECK(cufftXtFree(d_x));
    CUFFT_CHECK(cufftDestroy(plan));

    CUDA_CHECK(cudaDeviceReset());

    return 0;
}

1 Ответ

1 голос
/ 09 января 2020

Спасибо @RobertCrovella за ответ:

Начиная с CUDA 10.2.89 согласно документация пошаговый ввод и вывод не поддерживается для преобразований с несколькими GPU.

...