Knigts Landing とクロックダウンする石 part 2 (車 10)

昨日のまとめ

  • KNL はサイクル当たり2個の命令を実行できると資料にはある
  • 実際には1.69しか出ない

KNLのproduct briefによると、

http://www.intel.com/content/www/us/en/processors/xeon/xeon-phi-processor-product-brief.html

Frequency listed is nominal (non-AVX) TDP frequency. (略) For high-AVX instruction frequency, subtract 200 MHz

とあって、AVX負荷が高いと、1.3GHz から 200MHz 下がると書いてある。

今は、IPC=1.69 で、 1.69/2.0 = 0.845 ,クロックは 1.1/1.3 = 8.46 なので、200MHz 下がってるとすると計算は合う気がする。

が、これはおそらく現象を正しく表現していないように感じる。と、いうのは、今のLinuxでは、perf stat すると、実際に稼動したクロック数と、実時間から、プログラムが実際に動いたクロック数が取れるようになっているが、これで見てもクロックが下がっているようには見えない。

例えば、

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

#define INSN()								\
    __asm__ __volatile__("vfmadd231ps %zmm0, %zmm0, %zmm0\n\t"		\
			 "vfmadd231ps %zmm1, %zmm1, %zmm1\n\t"		\
			 "vfmadd231ps %zmm2, %zmm2, %zmm2\n\t"		\
			 "vfmadd231ps %zmm3, %zmm3, %zmm3\n\t"		\
			 "vfmadd231ps %zmm4, %zmm4, %zmm4\n\t"		\
			 "vfmadd231ps %zmm5, %zmm5, %zmm5\n\t"		\
			 "vfmadd231ps %zmm6, %zmm6, %zmm6\n\t"		\
			 "vfmadd231ps %zmm7, %zmm7, %zmm7\n\t"		\
			 "vfmadd231ps %zmm8, %zmm8, %zmm8\n\t"		\
			 "vfmadd231ps %zmm9, %zmm9, %zmm9\n\t"		\
			 "vfmadd231ps %zmm10, %zmm10, %zmm10\n\t"	\
			 "vfmadd231ps %zmm11, %zmm11, %zmm11\n\t");


int main()
{
  signal(SIGALRM, exit);
  alarm(1);

  while(1) {
    INSN();
    INSN();
    INSN();
    INSN();
    INSN();
    INSN();
    INSN();
  }
}

こういうコードで perf stat とると、

$ perf stat ./a.out 

 Performance counter stats for './a.out':

       1001.998233      task-clock (msec)         #    0.999 CPUs utilized          
                 2      context-switches          #    0.002 K/sec                  
                 0      cpu-migrations            #    0.000 K/sec                  
               117      page-faults               #    0.117 K/sec                  
     1,288,186,518      cycles                    #    1.286 GHz                      (50.06%)
   <not supported>      stalled-cycles-frontend  
   <not supported>      stalled-cycles-backend   
     2,200,109,120      instructions              #    1.71  insns per cycle          (75.06%)
        26,858,635      branches                  #   26.805 M/sec                    (75.02%)
            51,857      branch-misses             #    0.19% of all branches          (74.96%)

       1.002828425 seconds time elapsed

1.286 GHz とか出ている。

これは、CPU_CLK_UNHALTED の値から計算して出しているはず。CPU_CLK_UNHALTEDは、省電力機能によるクロック変動にあわせて変動するので、もしAVX-512に負荷をかけてクロックが下がるならば、これも下がって欲しいところだ。CPU_CLK_UNHALTEDが固定値だとしたら、rdtscとほぼ変わらないので、存在意義があやしくなる。


また、前世代のKNCでは、コア当たり最低2スレッド立てないとフル性能出ないという問題があったので、それと似た問題があるかもと思って試すものの、

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <omp.h>

#define INSN()								\
    __asm__ __volatile__("vfmadd231ps %zmm0, %zmm0, %zmm0\n\t"		\
			 "vfmadd231ps %zmm1, %zmm1, %zmm1\n\t"		\
			 "vfmadd231ps %zmm2, %zmm2, %zmm2\n\t"		\
			 "vfmadd231ps %zmm3, %zmm3, %zmm3\n\t"		\
			 "vfmadd231ps %zmm4, %zmm4, %zmm4\n\t"		\
			 "vfmadd231ps %zmm5, %zmm5, %zmm5\n\t"		\
			 "vfmadd231ps %zmm6, %zmm6, %zmm6\n\t"		\
			 "vfmadd231ps %zmm7, %zmm7, %zmm7\n\t"		\
			 "vfmadd231ps %zmm8, %zmm8, %zmm8\n\t"		\
			 "vfmadd231ps %zmm9, %zmm9, %zmm9\n\t"		\
			 "vfmadd231ps %zmm10, %zmm10, %zmm10\n\t"	\
			 "vfmadd231ps %zmm11, %zmm11, %zmm11\n\t");


int main()
{
  signal(SIGALRM, exit);
  alarm(1);

  omp_set_num_threads(2);

#pragma omp parallel for
  for (int i=0; i<2; i++) {
    while(1) {
      INSN();
      INSN();
      INSN();
      INSN();
      INSN();
      INSN();
      INSN();
    }
  }
}
$ numactl -C 0,64  perf stat  ./a.out  # 手元だと0と64が同じコアなので。

 Performance counter stats for './a.out':

       2003.569207      task-clock (msec)         #    1.996 CPUs utilized          
                 2      context-switches          #    0.001 K/sec                  
                 1      cpu-migrations            #    0.000 K/sec                  
               190      page-faults               #    0.095 K/sec                  
     2,561,111,631      cycles                    #    1.278 GHz                      (50.04%)
   <not supported>      stalled-cycles-frontend  
   <not supported>      stalled-cycles-backend   
     2,201,434,021      instructions              #    0.86  insns per cycle          (75.01%)
        27,798,335      branches                  #   13.874 M/sec                    (75.02%)
           171,238      branch-misses             #    0.62% of all branches          (74.99%)

       1.003819386 seconds time elapsed

2スレッドで、IPC=0.86、 コア当たりは、1.72 しか出ていない。


なんかめんどくなってきたので結論を書くと、二個目のFPUだけクロックが落ちて動いているように見える。

Agner先生が Knights Landing のレイテンシ/スループット出してるけど、

http://agner.org/optimize/instruction_tables.pdf


FP0 でしか実行できないvplzcntd とかは、

#define INSN()								\
    __asm__ __volatile__("punpcklbw %xmm0, %xmm0\n\t"		\
			 "punpcklbw %xmm1, %xmm1\n\t"		\
			 "punpcklbw %xmm2, %xmm2\n\t"		\
			 "punpcklbw %xmm3, %xmm3\n\t");		\

IPC 1.0 出る。


FP1 でしか実行できないkortestw … あれkortestw は asm で実行したらIPC 1.0 出るんだが…よくわからん…もういいや…(完)