2013-10-02 2 views
0

을 실행하지 않는 커널의 원인 부동의 혼합을 두 번하는 것은 통계 커널을 그 어디에서도 커널 내에서 VS2012에서 중단 점을 추가하고 이전의 변수 정의와 STDDEV 라인을 포함 할 때 :CUDA는 CUDA CI를 사용

double mean, stddev, sumOfValues, sumOfValuesSquared; 
unsigned int n; 

// acquire greater than 0 values for: sumOfValues, sumOfValuesSquared, and n 

stddev = (float)(sqrt((double)(n) * sumOfValuesSquared - (sumOfValues*sumOfValues))/(double)(n)); 

을 중단 점에 도달하지 않으며 커널이 실행되지 않습니다. 그 한 줄을 제거하면 커널이 실행됩니다. sqrt와 관련이 있다고 생각했지만 그렇지 않습니다. 다른 줄이있다 :

mean = sumOfValues/n; 

나는 그 줄을 사용할 때도 커널을 실행하지 않는다. CUDA에서 타입 변환에 대해 빠뜨린 것은 무엇입니까 (레지스터 문제입니까, 단 정밀도와 배정 밀도입니까?).

- 나는 1 스레드의 수를 조정 한 다음 1024을 처음 실행, 그것은과 두 번째, 내 브레이크 포인트로 이동

- UPDATE (2013년 10월 2일 중부 표준시 14시 25분) 스레드 수가 많으면 커널이 실행되지 않습니다. 아래 코드를 참조하십시오.

#include "stdafx.h" 

#include <stdio.h> 
#include <cuda.h> 
#include <cuda_runtime.h> 
#include <device_launch_parameters.h> 

typedef struct 
{ 
    unsigned int value; 
} ValueStruct; 

__global__ void FailsToExecute(ValueStruct *vs) 
{ 
    unsigned int numerator = vs->value; 
    unsigned int denominator= 3; 
    bool eject = false; 

    if(denominator > 0) 
    { 
     if(1.0f * numerator/denominator > 17.98f) 
      eject = true; 
     else 
      eject = false; 
    } 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    ValueStruct *vsHost; 
    ValueStruct *vsDevice; 

    cudaMallocHost((void **)&vsHost, sizeof(ValueStruct)); 
    cudaMalloc((void **)&vsDevice, sizeof(ValueStruct)); 

    vsHost->value = 54; 

    cudaMemcpy(vsDevice, vsHost, sizeof(ValueStruct), cudaMemcpyKind::cudaMemcpyHostToDevice); 

    dim3 blocks(5); 
    dim3 threads(1024); 

    FailsToExecute<<<blocks, threads>>>(vsDevice); 

    return 0; 
} 

레지스터 경계를 어떻게 계산합니까? 나는 그것에 대해 많이 모른다.

+0

'double'을 지원하는 아키텍처, 즉 컴퓨팅 기능 1.3 이상을 구현하는 코드를 작성하고 있습니까? – njuffa

+2

충분한 레지스터가없는 것 같습니다. 블록 당 스레드 수를 줄여 실행 가능한지 확인하십시오. – kangshiyin

+2

이것이 실제 코드가 아닌 것 같습니다. cuda-memcheck로 코드를 실행 해보십시오. for 루프에서 데이터 액세스 위반이있을 수 있습니다. 그렇지 않으면 완전한 재생 코드를 제공하십시오. SSCCE.org –

답변

0

가용 자원 (예 : 레지스터, 공유 메모리)보다 많은 자원을 필요로하는 커널은 실행되지 않습니다.

https://devtalk.nvidia.com/default/topic/545591/how-to-debug-kernel-throwing-an-exception-/?offset=16

인해 각 GPU 아키텍쳐 특정 커널의 조합에 필요한 자원의 정확한 계산을 위해 다른 할당 단위의 효과 : 여기에서 도시 된 바와 같이 이것은 예를 들면, 적절한 오류 검사에 의해 검출 될 수있다 특정 발사 구성은 사소한 일이 될 수 있습니다. 이러한 이유로 세분화 된 세부 사항을 통합 한 CUDA 점유율 계산기를 사용할 것을 제안합니다.

http://developer.download.nvidia.com/compute/cuda/CUDA_Occupancy_calculator.xls

+0

감사합니다 njuffa! 정확히 내가 필요로하는 것. – user2712376

+0

사용 가능한 점유율을 유지하기 위해 블록 당 스레드 수를 낮추는 것 외에도 코드를 디버깅 할 때 또 다른 주요 제한 요소가있었습니다. 제가 사용하고 있던 CUDA 카드가 기본 카드가 아니었지만 2 개의 모니터가 연결되어있었습니다. 모니터를 연결 해제 한 후에는 더 많은 자원을 사용할 수 있었고 따라서 더 많은 레지스터를 사용할 수있었습니다. 이것은 대부분의 경우에는 별 도움이되지 않지만 CUDA 코딩을 처음 접하는 경우 코드를 디버깅 할 때 자동으로 모니터 연결을 끊지 않는 것으로 간주됩니다. cudaCheckLaunchError는 커널 시작을 위해 cudaGetLastError를 추적하기위한 핵심 요소였습니다. – user2712376

+0

또한 Occupancy Excel 문서에서 지시 한대로 컴파일하는 동안 자세한 출력을 켜면 각 cuda 커널에 대해 컴파일러를 통해 할당 된 레지스터 및 기타 리소스의 수를 확인할 수 있습니다. 다중 힙/스택을 사용하는 동적 메모리 할당은 리소스 할당을 추적하는 것을 복잡하게 만들 수 있지만 디버깅 중에 모든 커널이 시작되고 cuda 함수가 실행 된 후에 cudaGetLastError를 사용하는 한 디버깅은 쉬운 프로세스입니다. 마지막으로, 현명한 사람들에게 ... GPGPU를 그래픽 카드로 사용하지 말고 최대한의 리소스를 컴퓨팅 즐거움에 활용할 수 있기를 바랍니다. – user2712376

0

는 NVCC 컴파일러 멀리 아무것도 커널을 최적화하는 것이 가능 : 현재 점유 스프레드 시트를 찾을 수 있습니까? 커널 함수를 살펴보면, 실제로 아무 것도하지 않기 때문에 이것이 0 명령으로 안전하게 최적화 될 수있는 방법을 알 수있었습니다. eject 때문에 문제가되지 않는다 eject 설정

__global__ void FailsToExecute(ValueStruct *vs) 
{ 
    unsigned int numerator = vs->value; 
    unsigned int denominator= 3; 
    bool eject = false; 

    if(denominator > 0) 
    { 
     if(1.0f * numerator/denominator > 17.98f) 
      eject = true; 
     else 
      eject = false; 
    } 
} 

다시 사용되지 않습니다. 그래서 우리는 그 두 가지 과제를 배제 할 수 있습니다. if() 조건의 표현식은 아무 것도 수정하지 않으며 if 문 중 하나의 분기에 대해 아무 작업도 수행하지 않으므로 if()를 제거 할 수있는 것처럼 보입니다. 그리고 계속해서 커널의 맨 위로 돌아가서, 아무 것도 최적화하지 않고 커널이 똑같은 결과를 만들어내는 것처럼 보입니다.

bool 배열과 같은 출력을 추가하고 그 배열에 eject의 결과를 저장하면 커널이 실행되는 것을 볼 수 있습니다.

+0

나는이 똑같은 것을 생각하고 그것을 시험해 보았다. 블록 당 스레드 수를 줄이면 스레드 (1024) 대신 스레드 (1), 코드 생성, 실행 및 추적이 가능해집니다 - PTX는 디스어셈블러에서 볼 수 있습니다. 그러나 당신이 제기 한 주제로 인해 코딩이 어려워졌습니다. NSIGHT를 사용하여 디버깅 할 때 가상 레지스터 인 '레지스터'는 최적화로 인해 일반적인 C 범위 개념을 따르지 않습니다. 감시 변수는 범위를 벗어납니다. 나는 그것이 필요하다고 확신한다, 나는 그것에 익숙해있다. 나는 그것이 내 사건의 코드에 영향을 미쳤다는 것을 믿지 않는다. – user2712376