Логарифм CUDA: nvprof обнаруживает операции одинарной точности с двойной точностью - PullRequest
0 голосов
/ 31 августа 2018

Я вычисляю "log (x)" с двойной точностью в CUDA, но когда я профилирую, он обнаруживает операции одинарной точности, используя метрику "flop_count_sp_special".

Я компилирую с "-arch = sm_30", чтобы обеспечить вычислительные возможности 3.0 и арифметику двойной точности, но я не могу найти способ гарантировать, что специальные функции вычисляются с двойной точностью. Это возможно?

1 Ответ

0 голосов
/ 31 августа 2018

Похоже, что вычисление CUDA с плавающей точкой двойной точности log включает (небольшое количество) вычислений с плавающей точкой одинарной точности. Я думаю, что это не должно быть поводом для беспокойства, само по себе.

Аппаратное обеспечение графического процессора не поддерживает собственное вычисление двойной точности log, поэтому при обнаружении компилятор заменяет инструкцию последовательностью операций (например, сложение, умножение и т. Д.), Предназначенных для выполнения вычисления. Мы можем подтвердить это простым примером:

$ cat t288.cu
#include <math.h>
#include <stdio.h>
__global__ void kernel(double *y)
{
  double x = *y;
  *y = log(x);
}

int main(){

  double *d_y, h_y = 10.0;
  cudaMalloc(&d_y, sizeof(double));
  cudaMemcpy(d_y, &h_y, sizeof(double), cudaMemcpyHostToDevice);
  kernel<<<1,1>>>(d_y);
  cudaDeviceSynchronize();
  cudaMemcpy(&h_y, d_y, sizeof(double), cudaMemcpyDeviceToHost);
  printf("val = %f\n", h_y);
}

$ nvcc -arch=sm_35 -o t288 t288.cu
$ cuda-memcheck ./t288
========= CUDA-MEMCHECK
val = 2.302585
========= ERROR SUMMARY: 0 errors
$ CUDA_VISIBLE_DEVICES="1" nvprof --metrics flop_count_dp,flop_count_sp,flop_count_sp_special ./t288
==14909== NVPROF is profiling process 14909, command: ./t288
==14909== Some kernel(s) will be replayed on device 0 in order to collect all events/metrics.
Replaying kernel "kernel(double*)" (done)
val = 2.302585rnal events
==14909== Profiling application: ./t288
==14909== Profiling result:
==14909== Metric result:
Invocations                               Metric Name                                    Metric Description         Min         Max         Avg
Device "Tesla K40m (0)"
    Kernel: kernel(double*)
          1                             flop_count_dp           Floating Point Operations(Double Precision)          44          44          44
          1                             flop_count_sp           Floating Point Operations(Single Precision)           0           0           0
          1                     flop_count_sp_special   Floating Point Operations(Single Precision Special)           1           1           1
$ cuobjdump -sass ./t288

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

        code for sm_35

Fatbin elf code:
================
arch = sm_35
code version = [1,7]
producer = cuda
host = linux
compile_size = 64bit

        code for sm_35
                Function : _Z6kernelPd
        .headerflags    @"EF_CUDA_SM35 EF_CUDA_PTX_SM(EF_CUDA_SM35)"
                                                                                  /* 0x088010fc10a010ac */
        /*0008*/                   MOV R1, c[0x0][0x44];                          /* 0x64c03c00089c0006 */
        /*0010*/                   MOV R2, c[0x0][0x140];                         /* 0x64c03c00281c000a */
        /*0018*/                   MOV R3, c[0x0][0x144];                         /* 0x64c03c00289c000e */
        /*0020*/                   LD.E.64 R12, [R2];                             /* 0xc5800000001c0830 */
        /*0028*/                   MOV32I R0, 0xfffffc01;                         /* 0x747ffffe009fc002 */
        /*0030*/                   ISETP.GT.AND P0, PT, R13, c[0x2][0x0], PT;     /* 0x5b481c40001c341e */
        /*0038*/                   MOV R4, R12;                                   /* 0xe4c03c00061c0012 */
                                                                                  /* 0x08ac1080a0a0a4ac */
        /*0048*/                   MOV R5, R13;                                   /* 0xe4c03c00069c0016 */
        /*0050*/              @!P0 DMUL R4, R4, 1.80143985094819840000e+16;       /* 0xc400021a80201011 */
        /*0058*/              @!P0 MOV R13, R5;                                   /* 0xe4c03c0002a00036 */
        /*0060*/                   IADD32I R6, R13, -0x1;                         /* 0x407fffffff9c3419 */
        /*0068*/                   ISETP.LT.U32.AND P1, PT, R6, c[0x2][0x4], PT;  /* 0x5b101c40009c183e */
        /*0070*/              @!P0 MOV R12, R4;                                   /* 0xe4c03c0002200032 */
        /*0078*/              @!P0 MOV32I R0, 0xfffffbcb;                         /* 0x747ffffde5a3c002 */
                                                                                  /* 0x08b88010a4a010ac */
        /*0088*/               @P1 BRA 0xc0;                                      /* 0x120000001804003c */
        /*0090*/                   MOV32I R8, 0x0;                                /* 0x74000000001fc022 */
        /*0098*/                   MOV32I R9, 0x7ff00000;                         /* 0x743ff800001fc026 */
        /*00a0*/                   DFMA R8, R4, +INF , R8;                        /* 0xb38023ff801c1021 */
        /*00a8*/                   FCMP.NEU R12, R8, RZ, R5;                      /* 0xdd6814007f9c2032 */
        /*00b0*/                   FCMP.NEU R13, R9, -QNAN , R5;                  /* 0xbd6817ff801c2435 */
        /*00b8*/                   BRA 0x240;                                     /* 0x12000000c01c003c */
                                                                                  /* 0x08a010b010a0a010 */
        /*00c8*/                   LOP32I.AND R4, R13, 0x800fffff;                /* 0x204007ffff9c3410 */
        /*00d0*/                   IMAD.U32.U32.HI R0, R13, 0x1000, R0;           /* 0xa2000008001c3401 */
        /*00d8*/                   LOP32I.OR R5, R4, 0x3ff00000;                  /* 0x211ff800001c1014 */
        /*00e0*/                   ISETP.LT.AND P0, PT, R5, c[0x2][0x8], PT;      /* 0x5b181c40011c141e */
        /*00e8*/                   MOV R4, R12;                                   /* 0xe4c03c00061c0012 */
        /*00f0*/              @!P0 IADD32I R7, R5, -0x100000;                     /* 0x407ff8000020141d */
        /*00f8*/              @!P0 IADD32I R0, R0, 0x1;                           /* 0x4000000000a00001 */
                                                                                  /* 0x08a010a01080a010 */
        /*0108*/              @!P0 MOV R5, R7;                                    /* 0xe4c03c0003a00016 */
        /*0110*/                   LOP32I.XOR R12, R0, 0x80000000;                /* 0x22400000001c0030 */
        /*0118*/                   DADD R6, R4, 1;                                /* 0xc38001ff801c1019 */
        /*0120*/                   MOV R8, RZ;                                    /* 0xe4c03c007f9c0022 */
        /*0128*/                   DADD R4, R4, -1;                               /* 0xcb8001ff801c1011 */
        /*0130*/                   MUFU.RCP64H R9, R7;                            /* 0x84000000031c1c26 */
        /*0138*/                   MOV32I R14, 0x8b7a8b04;                        /* 0x7445bd45821fc03a */
                                                                                  /* 0x08a01080a4a4a4a4 */
        /*0148*/                   DFMA R6, -R6, R8, c[0x2][0x10];                /* 0x9b882040021c181a */
        /*0150*/                   DFMA R6, R6, R6, R6;                           /* 0xdb801800031c181a */
        /*0158*/                   DFMA R6, R8, R6, R8;                           /* 0xdb802000031c201a */
        /*0160*/                   DMUL R8, R6, R4;                               /* 0xe4000000021c1822 */
        /*0168*/                   DFMA R8, R6, R4, R8;                           /* 0xdb802000021c1822 */
        /*0170*/                   MOV32I R15, 0x3ed0ee25;                        /* 0x741f6877129fc03e */
        /*0178*/                   MOV32I R13, 0x43300000;                        /* 0x74219800001fc036 */
                                                                                  /* 0x08a080a080a4a4a4 */
        /*0188*/                   DMUL R10, R8, R8;                              /* 0xe4000000041c202a */
        /*0190*/                   DFMA R14, R10, c[0x2][0x18], R14;              /* 0x5b803840031c283a */
        /*0198*/                   DFMA R14, R10, R14, c[0x2][0x20];              /* 0x9b803840041c283a */
        /*01a0*/                   DFMA R14, R10, R14, c[0x2][0x28];              /* 0x9b803840051c283a */
        /*01a8*/                   DADD R16, R4, -R8;                             /* 0xe3810000041c1042 */
        /*01b0*/                   DFMA R14, R10, R14, c[0x2][0x30];              /* 0x9b803840061c283a */
        /*01b8*/                   DADD R18, R16, R16;                            /* 0xe3800000081c404a */
                                                                                  /* 0x088880948880a080 */
        /*01c8*/                   DFMA R14, R10, R14, c[0x2][0x38];              /* 0x9b803840071c283a */
        /*01d0*/                   DADD R12, R12, c[0x2][0x50];                   /* 0x638000400a1c3032 */
        /*01d8*/                   DFMA R16, R10, R14, c[0x2][0x40];              /* 0x9b803840081c2842 */
        /*01e0*/                   DFMA R14, R12, c[0x2][0x58], R8;               /* 0x5b8020400b1c303a */
        /*01e8*/                   DFMA R4, -R4, R8, R18;                         /* 0xdb884800041c1012 */
        /*01f0*/                   DFMA R16, R10, R16, c[0x2][0x48];              /* 0x9b804040091c2842 */
        /*01f8*/                   DFMA R18, -R12, c[0x2][0x58], R14;             /* 0x5b8838400b1c304a */
                                                                                  /* 0x08aca4a4a4a08094 */
        /*0208*/                   DMUL R4, R6, R4;                               /* 0xe4000000021c1812 */
        /*0210*/                   DMUL R10, R10, R16;                            /* 0xe4000000081c282a */
        /*0218*/                   DADD R18, -R8, R18;                            /* 0xe3880000091c204a */
        /*0220*/                   DFMA R4, R8, R10, R4;                          /* 0xdb801000051c2012 */
        /*0228*/                   DADD R18, R4, -R18;                            /* 0xe3810000091c104a */
        /*0230*/                   DFMA R12, R12, c[0x2][0x60], R18;              /* 0x5b8048400c1c3032 */
        /*0238*/                   DADD R12, R14, R12;                            /* 0xe3800000061c3832 */
                                                                                  /* 0x080000000000b810 */
        /*0248*/                   ST.E.64 [R2], R12;                             /* 0xe5800000001c0830 */
        /*0250*/                   EXIT;                                          /* 0x18000000001c003c */
        /*0258*/                   BRA 0x258;                                     /* 0x12007ffffc1c003c */
        /*0260*/                   NOP;                                           /* 0x85800000001c3c02 */
        /*0268*/                   NOP;                                           /* 0x85800000001c3c02 */
        /*0270*/                   NOP;                                           /* 0x85800000001c3c02 */
        /*0278*/                   NOP;                                           /* 0x85800000001c3c02 */
                ......................



Fatbin ptx code:
================
arch = sm_35
code version = [6,2]
producer = cuda
host = linux
compile_size = 64bit
compressed
$

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

Глядя на дамп SASS, мы наблюдаем инструкцию с одинарной точностью:

        /*0130*/                   MUFU.RCP64H R9, R7;                            /* 0x84000000031c1c26 */

(мы можем подтвердить это с одинарной точностью, обратившись к документации )

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

Таким образом, «ожидается», что использование log может сообщить о некоторой (ненулевой) метрике flop_count_sp_special.

(Да, инструкции FCMP также имеют одинарную точность, но, по-видимому, они находятся в неиспользованном пути кода).

...