Выполните как умножение, так и сложение параллельно, используя cuda. - PullRequest
0 голосов
/ 09 мая 2018

У меня есть два вектора, и я хочу вычислить скалярное произведение этих двух векторов параллельно. Я был в состоянии сделать умножение каждого элемента параллельно и после этого сложения параллельно. Ниже приведен код, который я пробовал.

Но я хочу сделать как умножение, так и сложение параллельно . Это означает, что элементы, которые выполнили умножение, должны быть добавлены, даже если другие элементы еще не умножили. Надеюсь, вы поняли, что я сказал.

#include<stdio.h>
#include<cuda.h>
__global__ void dotproduct(int *a,int *b,int *c,int N)
{
    int k=N;
    int i=threadIdx.x;                      
    c[i]=a[i]*b[i];                         
    if(N%2==1)                          
        N=N+1;                          
    __syncthreads();                        
    while(i<(N/2))
    {
        if((i+1)*2<=k)
        {
            c[i]=c[i*2]+c[i*2+1];               
        }
        else
        {
            c[i]=c[k-1];
        }
        k=N/2;
        N=N/2;
        if(N%2==1&&N!=1)                            
            N=N+1;
        __syncthreads();                    //wait for all the threads to synchronize               
    }
}

int main()
{
    int N=10;                           //vector size
    int a[N],b[N],c[N];                     
    int *dev_a,*dev_b,*dev_c;                   
    cudaMalloc((void**)&dev_a,N*sizeof(int));           
    cudaMalloc((void**)&dev_b,N*sizeof(int));           
    cudaMalloc((void**)&dev_c,N*sizeof(int));           
    for(int i=0;i<N;i++)
    {
        a[i]=rand()%10;                     
        b[i]=rand()%10;                     
    }
    cudaMemcpy(dev_a,a,N*sizeof(int),cudaMemcpyHostToDevice);   
    cudaMemcpy(dev_b,b,N*sizeof(int),cudaMemcpyHostToDevice);   
    dotproduct<<<1,N>>>(dev_a,dev_b,dev_c,N);           
    cudaMemcpy(c,dev_c,N*sizeof(int),cudaMemcpyDeviceToHost);   
    for(int i=0;i<N;i++)
    {
        printf("%d,%d\n",a[i],b[i]);                

    }
    printf("the answer is : %d in GPU\n",c[0]);         

    cudaFree(dev_a);                        
    cudaFree(dev_b);                        
    cudaFree(dev_c);                        
    cudaThreadExit();                       
    return 0;

}

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

Я думаю, что есть также специальная инструкция PTX ISA, которая сразу производит точечный продукт (dp4a.atype.btype d, a, b, c;). Без особых усилий вы можете попытаться написать небольшую встроенную функцию сборки PTX. Проверьте документацию.

0 голосов
/ 11 мая 2018

Я не думаю, что имеет смысл выполнять умножение и сложение параллельно - все умножения будут занимать одно и то же время, и попытка выполнить разные инструкции в одно и то же время может снизить производительность.Но часть, в которой вы суммируете результаты умножения, может быть оптимизирована.

Вам много нужно использовать атомарные или случайные инструкции - прочтите это для хорошего объяснения: https://devblogs.nvidia.com/faster-parallel-reductions-kepler/

А если это не такупражнение, но реальная задача, я предлагаю вам использовать cuBLAS, в него встроены следующие функции: https://docs.nvidia.com/cuda/cublas/index.html#cublas-lt-t-gt-dot

0 голосов
/ 09 мая 2018

Возьмите ваше любимое сокращение (= сложение значений вектора) и измените его так, чтобы вместо каждого чтения из одного входного вектора вы выполняли два чтения с одинаковым индексом из двух входных векторов, и умножьте результаты.

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

...