Где хранятся литеральные константы float / int в Cuda

#cuda

#cuda

Вопрос:

Встречаются ли литеральные константы в ядрах, хранящихся в постоянной памяти? Например.,

 y = x * 3.14f; // x,y are floats.
  

3.14f Хранится в постоянной памяти и копируется в регистр перед умножением?

Ответ №1:

Согласно моему тестированию, эта константа, похоже, закодирована в потоке команд (т. Е. Она извлекается вместе с инструкциями):

 $ cat t1799.cu
__global__ void k(float *d){

  float y, x = *d;
  y = x * 3.14f;
  *d = y;
}
$ nvcc -c t1799.cu
$ cuobjdump -sass t1799.o

Fatbin elf code:
================
arch = sm_30
code version = [1,7]
producer = <unknown>
host = linux
compile_size = 64bit

        code for sm_30
                Function : _Z1kPf
        .headerflags    @"EF_CUDA_SM30 EF_CUDA_PTX_SM(EF_CUDA_SM30)"
                                                                           /* 0x22f04283f2804307 */
        /*0008*/                   MOV R1, c[0x0][0x44];                   /* 0x2800400110005de4 */
        /*0010*/                   MOV R2, c[0x0][0x140];                  /* 0x2800400500009de4 */
        /*0018*/                   MOV R3, c[0x0][0x144];                  /* 0x280040051000dde4 */
        /*0020*/                   LD.E R0, [R2];                          /* 0x8400000000201c85 */
        /*0028*/                   FMUL32I R4, R0, 3.1400001049041748047;  /* 0x310123d70c011c02 */
        /*0030*/                   ST.E [R2], R4;                          /* 0x9400000000211c85 */
        /*0038*/                   EXIT;                                   /* 0x8000000000001de7 */
        /*0040*/                   BRA 0x40;                               /* 0x4003ffffe0001de7 */
        /*0048*/                   NOP;                                    /* 0x4000000000001de4 */
        /*0050*/                   NOP;                                    /* 0x4000000000001de4 */
        /*0058*/                   NOP;                                    /* 0x4000000000001de4 */
        /*0060*/                   NOP;                                    /* 0x4000000000001de4 */
        /*0068*/                   NOP;                                    /* 0x4000000000001de4 */
        /*0070*/                   NOP;                                    /* 0x4000000000001de4 */
        /*0078*/                   NOP;                                    /* 0x4000000000001de4 */
                .................



Fatbin ptx code:
================
arch = sm_30
code version = [6,5]
producer = <unknown>
host = linux
compile_size = 64bit
compressed
$
  

Вероятно, вы можете провести такой анализ самостоятельно, если потратите некоторое время на документацию

Основные инструкции, представляющие интерес, следующие:

         /*0020*/      LD.E R0, [R2]; // float y, x = *d;  R0 is x
        /*0028*/      FMUL32I R4, R0, 3.1400001049041748047; // y = x * 3.14f; R4 is y
        /*0030*/      ST.E [R2], R4;   //       *d = y;
  

Синтаксис инструкции FMUL32I R4, R0, 3.1400001049041748047; дает понять, что 3.14 константа кодируется как непосредственный операнд в инструкции:

  FMUL32I
 ||  | Immediate
 ||  32-bit
 |Multiply
 Floating point
  

Код обращается к постоянной памяти в первых 3 инструкциях ядра, однако единственное, что имеет смысл, это:

 MOV R2, c[0x0][0x140];
  

который загружает адрес d параметра в регистр для косвенной загрузки регистра. Ни одна из этих загрузок из постоянной памяти не имеет ничего общего с 3.14 константой.

Хранится ли 3,14 f в постоянной памяти

Нет.

и скопированные в регистр перед умножением?

Нет.