В общем, я бы рекомендовал писать код CUDA в естественном стиле и позволить компилятору беспокоиться о локальном ветвлении.Помимо предикации, аппаратное обеспечение графического процессора также реализует инструкции типа «выбор».Используя каркас talonmies и придерживаясь исходного кода автора, я обнаружил, что один и тот же машинный код создается для обеих версий с помощью компилятора CUDA 4.0 для sm_20.Я использовал -keep для сохранения промежуточных файлов, а утилиту cuobjdump - для разборки.И троичный оператор, и оператор if транслируются в инструкцию FCMP, которая является инструкцией «выбора».
Пример случая, рассматриваемый талонмиями, на самом деле является особым случаем.Компилятор распознает некоторые общие идиомы исходного кода, такие как конкретное троичное выражение, часто используемое для выражения операций max () и min (), и генерирует код соответствующим образом.Эквивалентное выражение if не распознается как идиома.
__global__ void branchTest0(float *bp, float *d)
{
unsigned int tidx = threadIdx.x + blockDim.x*blockIdx.x;
float b = bp[tidx];
float a = (b>0)?1:0;
d[tidx] = a;
}
__global__ void branchTest1(float *bp, float *d)
{
unsigned int tidx = threadIdx.x + blockDim.x*blockIdx.x;
float b = bp[tidx];
float a;
if (b>0)a=1; else a =0;
d[tidx] = a;
}
code for sm_20
Function : _Z11branchTest1PfS_
/*0000*/ /*0x00005de428004404*/ MOV R1, c [0x1] [0x100];
/*0008*/ /*0x84009c042c000000*/ S2R R2, SR_Tid_X;
/*0010*/ /*0x94001c042c000000*/ S2R R0, SR_CTAid_X;
/*0018*/ /*0x10019de218000000*/ MOV32I R6, 0x4;
/*0020*/ /*0x20009ca320044000*/ IMAD R2, R0, c [0x0] [0x8], R2;
/*0028*/ /*0x1020dc435000c000*/ IMUL.U32.U32.HI R3, R2, 0x4;
/*0030*/ /*0x80211c03200d8000*/ IMAD.U32.U32 R4.CC, R2, R6, c [0x0] [0x20];
/*0038*/ /*0x90315c4348004000*/ IADD.X R5, R3, c [0x0] [0x24];
/*0040*/ /*0xa0209c03200d8000*/ IMAD.U32.U32 R2.CC, R2, R6, c [0x0] [0x28];
/*0048*/ /*0x00401c8584000000*/ LD.E R0, [R4];
/*0050*/ /*0xb030dc4348004000*/ IADD.X R3, R3, c [0x0] [0x2c];
/*0058*/ /*0x03f01c003d80cfe0*/ FCMP.LEU R0, RZ, 0x3f800, R0;
/*0060*/ /*0x00201c8594000000*/ ST.E [R2], R0;
/*0068*/ /*0x00001de780000000*/ EXIT;
....................................
Function : _Z11branchTest0PfS_
/*0000*/ /*0x00005de428004404*/ MOV R1, c [0x1] [0x100];
/*0008*/ /*0x84009c042c000000*/ S2R R2, SR_Tid_X;
/*0010*/ /*0x94001c042c000000*/ S2R R0, SR_CTAid_X;
/*0018*/ /*0x10019de218000000*/ MOV32I R6, 0x4;
/*0020*/ /*0x20009ca320044000*/ IMAD R2, R0, c [0x0] [0x8], R2;
/*0028*/ /*0x1020dc435000c000*/ IMUL.U32.U32.HI R3, R2, 0x4;
/*0030*/ /*0x80211c03200d8000*/ IMAD.U32.U32 R4.CC, R2, R6, c [0x0] [0x20];
/*0038*/ /*0x90315c4348004000*/ IADD.X R5, R3, c [0x0] [0x24];
/*0040*/ /*0xa0209c03200d8000*/ IMAD.U32.U32 R2.CC, R2, R6, c [0x0] [0x28];
/*0048*/ /*0x00401c8584000000*/ LD.E R0, [R4];
/*0050*/ /*0xb030dc4348004000*/ IADD.X R3, R3, c [0x0] [0x2c];
/*0058*/ /*0x03f01c003d80cfe0*/ FCMP.LEU R0, RZ, 0x3f800, R0;
/*0060*/ /*0x00201c8594000000*/ ST.E [R2], R0;
/*0068*/ /*0x00001de780000000*/ EXIT;
....................................