Arrays 缓慢的cuda计算时间

Arrays 缓慢的cuda计算时间,arrays,visual-c++,cuda,Arrays,Visual C++,Cuda,你好,我是cuda编程的初学者。这是我的密码 #include "book.h" #include <conio.h> #include <iostream> #include <stdlib.h> #include <time.h> #include <stdio.h> #include <math.h> #include <fstream> #include <cuda.h> #include

你好,我是cuda编程的初学者。这是我的密码

#include "book.h"
#include <conio.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <math.h>
#include <fstream>
#include <cuda.h> 
#include <curand.h>
#include <curand_kernel.h>
#define pop 1000
#define gen 1000
#define p gen*pop

using namespace std;

//random generator di GPU
__device__ float generate( curandState *globalState, int i) 
{
    //int ind = threadIdx.x;
    curandState localState = globalState[i];
    float RANDOM = curand_uniform( &localState );
    globalState[i] = localState;
    return RANDOM;
}

__global__ void setup_kernel ( curandState * state, unsigned long seed )
{
    int id = threadIdx.x;
    curand_init ( seed, id, 0, &state[id] );
}
__global__ void crossover(int *child, int *parent, curandState* globalState, int *x, int *y)
{
    int tid=(blockIdx.x*blockDim.x)+threadIdx.x;
    int distance1,distance2;
    int tmp;
    if(tid<pop-1)
    {

        for(int j=0;j<gen;j++)
        {

            if (j == 0)
            {
                child[(tid*gen)+j]= generate(globalState,tid) * gen;//ini hassilnya tdak random bagus
            }
            else
            {

                distance1=sqrt((float)( pow ((double)(x[parent[(tid*gen)+j]]-x[child[(tid*gen)+(j-1)]]),2.0)+pow((double)(y[parent[(tid*gen)+j]]-y[child[(tid*gen)+(j-1)]]),2.0)));
                distance2=sqrt((float)( pow ((double)(x[parent[((tid+1)*gen)+j]]-x[child[(tid*gen)+(j-1)]]),2.0)+pow((double)(y[parent[((tid+1)*gen)+j]]-y[child[(tid*gen)+(j-1)]]),2.0)));             
                //anak[(tid*gen)+j]=tid;//thread dimana komputasi jalan
                if (distance1<distance2)
                {
                    tmp=parent[(tid*gen)+j];
                }

                tmp=parent[((tid+1)*gen)+j];

                bool same;
                do
                {
                    same=false;
                    for(int i=0;i<j;i++)
                    {
                        if (child[(tid*gen)+i] == tmp)
                        {
                            same=true;
                            tmp=generate(globalState, tid)*gen ;
                        }
                    }child[(tid*gen)+j]=tmp;
                }while(same);

            }
        }
    }
    else
    {
        for(int j=0;j<gen;j++)
        {
            if (j == 0)
            {
                child[(tid*gen)+j]= generate(globalState,tid) * gen;
            }
            else
            {
                distance1=sqrt((float)(pow((double)(x[parent[(tid*gen)+j]]-x[child[(tid*gen)+(j-1)]]),2.0))+pow((double)(y[parent[(tid*gen)+j]]-y[child[(tid*gen)+(j-1)]]),2.0));
                distance2=sqrt((float)(pow((double)(x[parent[j]]-x[child[(tid*gen)+(j-1)]]),2.0))+pow((double)(y[parent[j]]-y[child[(tid*gen)+(j-1)]]),2.0));

                if (distance1<distance2)
                {
                    tmp=parent[(tid*gen)+j];
                }

                tmp=parent[j];

                bool samme;
                do
                {
                    samme=false;
                    for(int i=0;i<j;i++)
                    {
                        if (child[(tid*gen)+i] == tmp)
                        {
                            samme=true;
                            tmp=generate(globalState, tid)*gen ;
                        }
                    }child[(tid*gen)+j]=tmp;
                }while(samme);

            }
        }

    }
}
int main (void)
{
    srand(time(NULL));
    float time1;
    int x[gen],y[gen];
    int *dev_x,*dev_y;
    double MAX = 100.;
    int* parent=new int [p];
    int* child=new int [p];
    int *dev_parent;
    int *dev_child;
    for (int i=0;i<gen;i++)
    {
        float unirand = ((float)rand()/(float)RAND_MAX);
         x[i] = MAX*unirand;
    }
    for (int i=0;i<gen;i++)
    {
        float unirand = ((float)rand()/(float)RAND_MAX);
        y[i] = MAX*unirand;
    }
    HANDLE_ERROR( cudaMalloc( (void**)&dev_x, gen * sizeof(int) ) );
    HANDLE_ERROR( cudaMalloc( (void**)&dev_y, gen * sizeof(int) ) );
    HANDLE_ERROR( cudaMemcpy( dev_x, x, gen * sizeof(float), cudaMemcpyHostToDevice ) );
    HANDLE_ERROR( cudaMemcpy( dev_y, y, gen * sizeof(float), cudaMemcpyHostToDevice ) );
    bool check;
    for (int i=0;i<pop;i++)
    {
        for (int j=0;j<gen;j++)
        {
            do
            {
                check = false;
                parent[ ((i*gen)+j) ] = rand()%gen;
                for (int k=0;k<j;k++)
                {
                    if (parent[ ((i*gen)+j) ] == parent[ ((i*gen)+k) ])
                    {
                        check = true;
                        break;
                    }
                }

            }
            while (check);

        }
    }
    HANDLE_ERROR( cudaMalloc( (void**)&dev_parent, p * sizeof(int) ) );
    HANDLE_ERROR( cudaMalloc( (void**)&dev_child, p * sizeof(int) ) );
    HANDLE_ERROR( cudaMemcpy (dev_parent, parent, p * sizeof(int), cudaMemcpyHostToDevice ) );

    curandState* devStates;
    HANDLE_ERROR(cudaMalloc ( &devStates, pop * sizeof( curandState ) ));
    cudaEvent_t start, stop;
    HANDLE_ERROR( cudaEventCreate(&start) );
    HANDLE_ERROR( cudaEventCreate(&stop) );
    HANDLE_ERROR( cudaEventRecord(start, 0) );
    setup_kernel <<< pop, 1 >>> ( devStates, unsigned(time(NULL)) );
    crossover<<<pop, 1>>>(dev_child,dev_parent,devStates,dev_x,dev_y);
    cudaDeviceSynchronize();
    HANDLE_ERROR( cudaEventRecord(stop, 0) );
    HANDLE_ERROR( cudaEventSynchronize(stop) );
    HANDLE_ERROR( cudaEventElapsedTime(&time1, start, stop) );
    HANDLE_ERROR( cudaMemcpy ( child, dev_child, p * sizeof(int),cudaMemcpyDeviceToHost ) );
    printf("crossover:  %3.1f ms \n", time1);
    cudaFree( dev_child );
    cudaFree( dev_parent );
    cudaFree( devStates );
    cudaFree( dev_x );
    cudaFree( dev_y );
    system("pause");
    return 0;
}

cuda中的执行时间为17943毫秒。请帮我快点。有时,如果gen>500 n pop>500,则cudaMemcpyDeviceToHost行中出现错误。谢谢

您可能有很多方法可以提高性能,但我希望最大的飞跃来自于修复您的启动配置。部分>告诉GPU您有pop块,每个块都有一个线程。要使GPU内核高效,您需要许多块,每个块都有许多线程

虽然最佳块大小因具体情况而异,但对于所有当前GPU,128倍的块大小通常是最有效的。也就是说,您需要使用类似>或>的东西来调用内核。您将在此处启动的线程总数为x*128或y*256,您需要相应地计算x或y。注意:正如每个块有一个线程是低效的一样,每个网格有一个块也是低效的。您通常希望启动50多个块


当然,要实现上述目标,您需要比当前工作更多的元素。1000路并行对于当前最便宜的GPU来说是不够的。

两个非常响亮的性能警钟:我知道你在距离计算中使用了双精度为什么?你打电话给pow只是为了再次平方一个值,为什么?谢谢你回答我的问题。ii不使用双精度距离。我使用的是整数距离1,整数距离2。因为我用的是欧几里德公式。你把整数转换成双倍数,只是为了通过调用pow将它们平方,然后再转换回整数-这太疯狂了,当你只需要一个整数的时候。