CUDA добавить строки матрицы


Я пытаюсь сложить строки матрицы 4800x9600 вместе, в результате чего получается матрица 1x9600.

То, что я сделал, это разбил 4800x9600 на 9600 матриц длиной 4800 каждая. Затем я выполняю сокращение на 4800 элементах. Проблема в том, что это очень медленно...

У кого-нибудь есть предложения?

В основном, я пытаюсь реализовать сумму MATLAB(...) функция.

Вот код, который я проверил, работает нормально, просто это действительно так. медленно:

void reduceRows(Matrix Dresult,Matrix DA)
{
        //split DA into chunks
        Matrix Dchunk;
        Dchunk.h=1;Dchunk.w=DA.h;
        cudaMalloc((void**)&Dchunk.data,Dchunk.h*Dchunk.w*sizeof(float));

        Matrix DcolSum;
        DcolSum.h=1;DcolSum.w=1;
        //cudaMalloc((void**)&DcolSum.data,DcolSum.h*DcolSum.w*sizeof(float));

        int i;
        for(i=0;i<DA.w;i++)   //loop over each column
        {
                //printf("%d ",i);
                cudaMemcpy(Dchunk.data,&DA.data[i*DA.h],DA.h*sizeof(float),cudaMemcpyDeviceToDevice);
                DcolSum.data=&Dresult.data[i];
                reduceTotal(DcolSum,Dchunk);
        }
        cudaFree(Dchunk.data);
}
Матрица

Определяется следующим образом:

typedef struct{
        long w;
        long h;
        float* data;
}Matrix;

ReduceTotal() просто вызывает стандартное сокращение NVIDIA, суммирует все элементы в Dchunk и помещает ответ в DcolSum.

Я собираюсь сделать все это на процессоре, если не смогу найти ответ... ; (

Заранее большое спасибо,

3 2

3 ответа:

Вместо того, чтобы петлять по каждому столбцу, выполните параллелизацию по столбцам. Каждый из 4600 потоков суммирует 9600 записей в своем столбце и помещает сумму в соответствующее место в результирующем векторе.

Если вы ищете библиотеку, чтобы упростить работу с Cuda, я настоятельно рекомендую Thrust: http://code.google.com/p/thrust/

Используя функцию тяги, я бы создал функтор для хранения указателя вашей матрицы в памяти устройства, а затем сопоставил бы его с последовательностью индексов столбцов. То оператор () функтора взял бы индекс, суммировал бы все в этом столбце матрицы и вернул бы сумму. Тогда ваша сумма будет сидеть в push:: device_vector без каких-либо копий памяти (или даже прямых вызовов CUDA).

Ваш функтор может выглядеть примерно так:

struct ColumnSumFunctor {
    const Matrix matrix;

    // Make a functor to sum the matrix
    ColumnSumFunctor(const Matrix& matrix);

    // Compute and return the sum of the specified column
    __device__
    int operator()(const int& column) const;
};

Сокращение-это очень простая операция в GPGPU, она должна быть быстрой, и 9600 раз сокращения также не должны быть медленными.

Какую видеокарту вы используете?

Я предлагаю разбить его на 9600 массивов, каждый раз, когда вы уменьшаете массив из 4800 элементов в один результат. Вместо reduceTotal, я предлагаю вам использовать CUDPP для выполнения операции сокращения, CUDPP-это как STL для CUDA. Он реализуется с беспокойством на спектакль.

Http://code.google.com/p/cudpp/

Я думаю, что ваша проблема заключается в том, что вы запускаете ядра 9600X2. Это должен быть простой алгоритм для выражения в виде одного ядра.

Самый наивный способ реализации этого не будет объединять память, но это вполне может быть быстрее, чем то, как вы делаете это сейчас.

После того, как вы получили наивный способ работы, затем объедините ваши чтения памяти: например, пусть каждый поток в блоке прочитает 16 последовательных плавающих потоков в общую память, syncthreads, а затем накопит соответствующие 16 плавающих потоков в общую память. регистр, synthreads, затем повторите

Вычислительный SDK имеет множество примеров методов сокращения.