문제

CUDA에서 몇 가지 코드를 테스트하고 있습니다 (나는 CUDA에 새로운 것이고 이것은 첫 번째 응용 프로그램입니다).지금까지 CPU에서 연속적으로 코드를 실행하여 얻은 CUDA에서 결과를 얻었습니다.나는 Visual Studio 2010을 사용하고 있으며 빌드 구성은 디버그입니다.그러나 빌드 구성을 "릴리스"로 변경하자마자 잘못된 결과를 얻기 시작합니다.나는 그 순간에 누드 시아 포럼을 사용할 수 없었습니다.CUDA 경험을 가진 사람이 문제를 지적 할 수 있습니까?코드는 다음과 같습니다 입니다

__global__ void MyKernel(int *Nptr,int *deltaptr, double *gravityptr, double *separationptr, double *fconptr, double *xForce, double *yForce, double *zForce,
double *xPos, double *yPos, double *zPos )
{
int N = *Nptr;
int delta= *deltaptr;
double gravity= *gravityptr;
double separation = *separationptr;
double fcon = *fconptr;

double len=0.0;
double r12X =0.0;
double r12Y =0.0;
double r12Z =0.0;
double PE=0.0;


int nx = blockDim.x * blockIdx.x + threadIdx.x;//use this place of nx
//int ny = blockDim.x * blockIdx.x + threadIdx.y;//use this place of ny
int ny = blockDim.y * blockIdx.y + threadIdx.y;
//printf("nx:%d ny:%d\n", nx,ny);

if(!(nx< N && ny <N))
    return;
//printf("nx:%d ny:%d\n", nx,ny);


xForce[nx*N+ny] = 0.0;
yForce[nx*N+ny] = -gravity;
zForce[nx*N+ny] = 0.0;

int lowerValuedx = maxOnDevice(nx-delta,0);
int upperValuedx=minOnDevice(nx+delta+1,N);
for(int dx=lowerValuedx; dx<upperValuedx;dx++)
{
    int lowerValuedy=maxOnDevice(ny-delta,0);
    int upperValuedy=minOnDevice(ny+delta+1,N);
    for(int dy=lowerValuedy; dy<upperValuedy;dy++)
    {
        len=sqrt((double)((nx-dx)*(nx-dx)+(ny-dy)*(ny-dy)) ) *separation;
        bool condition = ny!=dy;
        bool condition1 = nx!=dx;

        //if (nx!=dx || ny!=dy)
        if (condition || condition1)
        {
            r12X = xPos[dx*N+dy] - xPos[nx*N+ny];
            r12Y = yPos[dx*N+dy] - yPos[nx*N+ny];
            r12Z = zPos[dx*N+dy] - zPos[nx*N+ny];
            xForce[nx*N+ny] = xForce[nx*N+ny] +fcon*normxOnDevice(r12X,r12Y,r12Z)*(magOnDevice(r12X,r12Y,r12Z)-len);
            yForce[nx*N+ny]= yForce[nx*N+ny] +fcon*normyOnDevice(r12X,r12Y,r12Z)*(magOnDevice(r12X,r12Y,r12Z)-len);
            zForce[nx*N+ny]= zForce[nx*N+ny] +fcon*normzOnDevice(r12X,r12Y,r12Z)*(magOnDevice(r12X,r12Y,r12Z)-len);


        }
    }
}   
.

}

감사합니다

도움이 되었습니까?

해결책

CPU와 GPU 결과 사이에는 수치 차이가 있고 GPU에서 디버그 및 릴리스 사이에 존재하는 것이 비정상적인 것은 아닙니다. 이것은 결과 집합이 올바르지 않지만 다른 것보다 정확할 수 있습니다. 숫자 불일치로 이어질 수있는 다양한 메커니즘에 대해 설명하는 NVIDIA의 다음 백서를 참조하십시오.

http://developer.download. nvidia.com/assets/cuda/files/nvidia-cuda-floating-point.pdf

NVCC Flag -fmad= False가보고있는 차이점을 제거하는지 여부를 확인할 수 있습니다. 이는 FMA / FMAD 병합으로 인한 것으로 나타납니다. 따라서 무해합니다.

GPU는 부동 소수점을 결합한 FMAD 및 FMA (융합 된 곱하기 첨가) 동작을 제공하여 단일 조작으로 부동 소수점 곱셈을 결합합니다. 이는 결합 된 작동이 전형적으로 각 구성 요소의 각각과 비슷한 양의 시간을 소비하기 때문에 성능에 도움이됩니다. 그러나 결합 된 작동 중 하나의 반올림 거동은 두 개의 개별 반올림 된 작업을 사용하는 것과는 다릅니다.

단일 정밀 FMAD (컴퓨팅 능력 <2.0)는 곱하기 결과를 자르고 IEEE-754 원형으로 가장 가까운 -754에 따라 최종 추가의 결과를 둥글게합니다. 대조적으로 FMA (컴퓨팅 기능에 대한 단일 정밀도>= 2.0 및 이중 정밀도)가 해제되지 않은 양의 제품을 계산하며 세 번째 피연산자를 추가하고 IEEE-754 원형으로 가장 가까운 -754에 따라 최종 합계를 반올림합니다. -조차. 이 단일 반올림 때문에 FMA가 제공하는 평균 정확도는 두 개의 별도로 둥근 작업을 사용하는 것보다 우수합니다. FMA 작업은 IEEE-754 부동 소수점 표준의 2008 버전에 지정됩니다.

기본적으로 릴리스 빌드의 경우 CUDA 컴파일러는 최상의 성능을 얻기 위해 병합 된 작업 (FMAD, FMA)을 공격적으로 생성합니다. 즉, 컴파일러 기본값은 -fmad= true 컴파일러가 부동 소수점 곱셈을 병합하고 추가 할 수있게합니다. -fmad= false를 지정하면 곱셈 및 추가의 병합이 금지되어 대부분의 CPU가 FMA 작업을 제공하지 않기 때문에 일반적으로 CPU 결과와 일관성을 향상시킵니다. 병합 된 작업의 사용을 분명히 비활성화하는 것은 성능에 부정적인 영향을 미칩니다. 따라서 -fmad= false는 주로 정신 검사로 유용합니다.

정확도 문제가 의심되는 경우, 일반적으로 CPU 버전을 사용하는 대신 CPU 버전과 GPU 모두의 오류를 정확하게 평가하기 위해 고정밀 기준 구현 (예 : 쿼드 정밀 또는 이중 이중 기술을 기반으로 한 것)과 비교를 권장합니다. 참조로서 (CPU 결과가 라운드 오프 오류의 영향을받는 경우)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top