2012-03-01 4 views
1

Чтобы сэкономить на глобальных передачах памяти, и потому что все шаги кода работают индивидуально, я попытался объединить все ядра в одно ядро, причем первые 2 (из 3) шаги выполняются как устройство звонки, а не глобальные звонки. Ошибка во второй половине первого шага.Вторая итерационная авария - заказ неактуальен

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

После изучения кода, а также я мог и выполнял его несколько раз с разными точками возврата, я нашел, что заставляет его сбой.

__device__ 
void IntersectCone(float* ModDistance, 
       float* ModIntensity, 
       float3 ray, 
       int threadID, 
       modParam param) 
{ 

bool ignore = false; 

float3 normal = make_float3(0.0f,0.0f,0.0f); 
float3 result = make_float3(0.0f,0.0f,0.0f); 
float normDist = 0.0f; 
float intensity = 0.0f; 

float check = abs(Dot(param.position, Cross(param.direction,ray))); 
if(check > param.r1 && check > param.r2) 
    ignore = true; 

float tran = param.length/(param.r2/param.r1 - 1); 
float length = tran + param.length; 
float Lsq = length * length; 
float cosSqr = Lsq/(Lsq + param.r2 * param.r2); 

//Changes the centre position? 
float3 position = param.position - tran * param.direction; 

float aDd = Dot(param.direction, ray); 
float3 e = position * -1.0f; 
float aDe = Dot(param.direction, e); 
float dDe = Dot(ray, e); 
float eDe = Dot(e, e); 
float c2 = aDd * aDd - cosSqr; 
float c1 = aDd * aDe - cosSqr * dDe; 
float c0 = aDe * aDe - cosSqr * eDe; 

float discr = c1 * c1 - c0 * c2; 

if(discr <= 0.0f) 
    ignore = true; 

if(!ignore) 
{ 
    float root = sqrt(discr); 
    float sign; 

    if(c1 > 0.0f) 
     sign = 1.0f; 
    else 
     sign = -1.0f; 

    //Try opposite sign....? 
    float3 result = (-c1 + sign * root) * ray/c2; 


    e = result - position; 
    float dot = Dot(e, param.direction);   
    float3 s1 = Cross(e, param.direction);   
    float3 normal = Cross(e, s1); 

    if((dot > tran) || (dot < length)) 
    { 
     if(Dot(normal,ray) <= 0) 
     { 
      normal = Norm(normal); //This stuff (1) 
      normDist = Magnitude(result); 
      intensity = -IntensAt1m * Dot(ray, normal)/(normDist * normDist); 
     } 
    } 
} 
ModDistance[threadID] = normDist; and this stuff (2) 
ModIntensity[threadID] = intensity; 
} 

Есть две вещи, которые я могу сделать, чтобы сделать это не крах, и от которых отпадают точка функции: Если я не пытаюсь писать ModDistance [] и ModIntensity [], или если я не пишите в normDist и интенсивность.

Первые случайные исключения выбрасываются кодом выше, но нет, если какой-либо из блоков закомментирован. Кроме того, программа вызывается только во второй раз, когда вызывается эта процедура.

Были попытки понять это весь день, любая помощь была бы фантастической.

Код, который вызывает это:

int subrow = threadIdx.y + Mod_Height/2; 
int threadID = subrow * (Mod_Width+1) + threadIdx.x;   
int obsY = windowY + subrow; 
float3 ray = CalculateRay(obsX,obsY); 

if(!IntersectSphere(ModDistance, ModIntensity, ray, threadID, param)) 
{ 
    IntersectCone(ModDistance, ModIntensity, ray, threadID, param); 
} 

subrow = threadIdx.y; 
threadID = subrow * (Mod_Width+1) + threadIdx.x;   
obsY = windowY + subrow; 
ray = CalculateRay(obsX,obsY); 

if(!IntersectSphere(ModDistance, ModIntensity, ray, threadID, param)) 
{ 
    IntersectCone(ModDistance, ModIntensity, ray, threadID, param); 
} 
+0

Симптом ошибки показывался в другом месте, чем источник ошибки. Весь ядро ​​было слишком большим и поэтому не могло назначать достаточное количество регистров. – 3Pi

+0

Две строки, которые вы назвали, могут служить отправной точкой. (1) Как выглядит функция 'Norm()'? Я ожидаю, что он вернет скаляр, а не вектор? Тот же вопрос для 'Magnitude()'. (2) Я могу увидеть эту строку только в том случае, если 'threadID' был вне пределов. –

+0

А как раз видел ваш комментарий. Хорошая находка. –

ответ

2

Ядро работает из ресурсов. Как сообщается в комментариях, он выдавал ошибку CudaErrorLaunchOutOfResources.

Чтобы избежать этого, вы должны указать спецификатор __launch_bounds__, чтобы указать размеры блоков, которые вы хотите для своего ядра. Это заставит компилятор обеспечить достаточное количество ресурсов. Подробные сведения см. В руководстве по программированию CUDA: __launch_bounds__.