Arrays 缓慢的cuda计算时间
你好,我是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
#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将它们平方,然后再转换回整数-这太疯狂了,当你只需要一个整数的时候。