Cortex-A15 vs Jaguar
Nexus10 は Cortex A15 のために買ったはずが全然何も調べてないなと思ってそういえばTemashも出たことだしたまには比較しようと思った。
環境
Cortex A15(以下A15) | Jaguar | Haswell(参考) | |
Exynos 5250 | a4-1250 | i7-4700MQ | |
コア数 | 2 | 2 | 4C8T |
クロック | 1.7 | 1.0 | 2.4 |
CPU 消費電力目安
#include <pthread.h> #include <stdlib.h> #include <stdio.h> static void * loop(void *p) { volatile float x= 0; volatile int y = 0; while (1) { x++; y++; } } int main(int argc, char **argv) { int nthread = 2; int i; pthread_t *threads; if (argc > 1) { nthread = atoi(argv[1]); } threads = malloc(sizeof(pthread_t) * nthread); for (i=0; i<nthread-1; i++) { pthread_create(&threads[i], NULL, loop, NULL); } while (1); }
こういうのを回してアイドル時と実行時の消費電力の差分
A15 | Jaguar | |
アイドル時[W] | 2 | 8 |
実行時[W] | 7 | 12 |
消費電力かも[W] | 5 | 4 |
CPUの消費電力って定義が難しいのでこの数値を持ってうんぬんは言えないと思うが、まあいい勝負してると言える。
SBU
SBU(http://www.linuxfromscratch.org/~bdubbs/about.html : make install含んでないが…)
Cortex-A15のほうがはやい。へー。binutilsはアーキテクチャごとにコンパイルするソース違うので公平ではないが…
# 全部 make -j2 です i7-4700MQ: real 0m52.016s user 1m8.163s sys 0m15.614s a4-1250 (Jaguar 1.0GHz x 2コア): real 4m30.359s user 6m41.989s sys 0m48.279s exynos5250 (Cortex-A15 1.7GHz x 2コア): real 3m22.788s user 4m27.405s sys 0m38.650s
SunSpider
なんか大体一緒ではという感想を持ちそうになるな。
とくに検証もしないでベンチとってグラフ書くだけとかアレな感想風味が強いな。
まあJavaScriptとかJITの完成度の違いの影響を受けてそう。
はやい
cairo
cairoって単純なのだとSIMDっぽい演算で複雑だとジオメトリックな演算(て何?)律速になるから、パラメータ変えるだけで色々ベンチマーク作れると思うんだよね。
#include <cairo.h> #include <sys/time.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int width, height; cairo_surface_t *s0; int nloop; static double usec() { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000.0 + tv.tv_usec; } typedef void (*bench_t) (void); static void clear() { cairo_t *c = cairo_create(s0); cairo_set_source_rgb(c, 0, 0, 0); cairo_rectangle(c, 0, 0, width, height); cairo_fill(c); cairo_destroy(c); } static void clear_alpha() { cairo_t *c = cairo_create(s0); cairo_set_source_rgba(c, 0, 0, 1, 0.01); cairo_rectangle(c, 0, 0, width, height); cairo_fill(c); cairo_destroy(c); } static void grad() { cairo_t *c = cairo_create(s0); cairo_pattern_t *pat = cairo_pattern_create_linear(0, 0, width, height); cairo_pattern_add_color_stop_rgb(pat, 0, 1, 1, 1); cairo_pattern_add_color_stop_rgb(pat, 1, 0, 0, 0); cairo_set_source(c, pat); cairo_rectangle(c, 0, 0, width, height); cairo_fill(c); cairo_destroy(c); cairo_pattern_destroy(pat); } static void moji() { cairo_t *c = cairo_create(s0); cairo_pattern_t *pat = cairo_pattern_create_linear(0, 0, width, height); cairo_pattern_add_color_stop_rgb(pat, 0, 1, 1, 1); cairo_pattern_add_color_stop_rgb(pat, 1, 0, 0, 0); cairo_set_source(c, pat); cairo_move_to(c, 100, 100); cairo_rotate(c, 1.5); cairo_set_font_size(c, 32); cairo_set_line_width(c, 1.0); cairo_text_path(c, "abcdefghijklmnopqrstuvwxyz"); cairo_stroke(c); cairo_destroy(c); cairo_pattern_destroy(pat); } static void curve() { cairo_t *c = cairo_create(s0); cairo_pattern_t *pat = cairo_pattern_create_linear(0, 0, width, height); int i; cairo_pattern_add_color_stop_rgb(pat, 0, 1, 1, 1); cairo_pattern_add_color_stop_rgb(pat, 1, 0, 0, 0); cairo_move_to(c, 100, 100); for (i=0; i<8; i++) { cairo_curve_to(c, 125+i*100, 100, 125+i*100, 1000, 150+i*100, 1000 ); cairo_curve_to(c, 175+i*100, 1000, 175+i*100, 100, 200+i*100, 100 ); } cairo_stroke(c); cairo_destroy(c); cairo_pattern_destroy(pat); } static void run(bench_t b) { double tb, te; int i; b(); tb = usec(); for (i=0; i<nloop; i++) { b(); } te = usec(); printf("%f\n", (te-tb)/nloop); } int main(int argc, char **argv) { int t = 0; int opt; width = 1024; height = 1024; nloop = 1000; while ((opt = getopt(argc, argv, "i:t:")) != -1) { switch (opt) { case 't': t = atoi(optarg); break; case 'i': nloop = atoi(optarg); break; default: puts("usage run -i nloop -t type"); return 1; } } s0 = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); switch (t) { case 0: run(clear); break; case 1: run(grad); break; case 2: run(moji); break; case 3: run(curve); break; case 4: run(clear_alpha); break; } if (1) { cairo_surface_write_to_png(s0, "out.png"); } return 0; }
Jaguar $ ./run-x86 -t 0 -i 128 # fillするだけ 1729.984375 $ ./run-x86 -t 1 -i 4 # グラデfill 55545.750000 $ ./run-x86 -t 2 -i 16 # font 36090.875000 $ ./run-x86 -t 3 -i 16 # curve 7033.187500 $ ./run-x86 -t 4 -i 16 # alpha fill 3071.437500 A15 # ./run -t 0 -i 128 721.210938 # ./run -t 1 -i 4 85699.000000 # ./run -t 2 -i 16 37483.875000 # ./run -t 3 -i 16 5625.562500 # ./run -t 4 -i 16 2835.687500
これちょっと真面目に調べるから待って。
himenoBMT
まあコードあってすぐ数字出るやつもう一個ぐらい出しとくか
jaguar $ ./bmt mimax = 257 mjmax = 129 mkmax = 129 imax = 256 jmax = 128 kmax =128 cpu : 44.229731 sec. Loop executed for 200 times Gosa : 1.245715e-03 MFLOPS measured : 619.968211 Score based on MMX Pentium 200MHz : 19.211906 a15 # ./bmt mimax = 257 mjmax = 129 mkmax = 129 imax = 256 jmax = 128 kmax =128 cpu : 47.590516 sec. Loop executed for 200 times Gosa : 1.245715e-03 MFLOPS measured : 576.186802 Score based on MMX Pentium 200MHz : 17.855184 haswell $ ./bmt mimax = 257 mjmax = 129 mkmax = 129 imax = 256 jmax = 128 kmax =128 cpu : 8.620606 sec. Loop executed for 200 times Gosa : 1.245715e-03 MFLOPS measured : 3180.870022 Score based on MMX Pentium 200MHz : 98.570500
気が向いたら真面目に調べるかも。
cairo 解析 -t 0
fillしてるだけ
A15 | Jaguar |
721.210938 | 1729.984375 |
: extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) : _mm_store_si128 (__m128i *__P, __m128i __B) : { : *__P = __B; 1.49 : 73863: movdqa %xmm0,(%rdx) 0.00 : 73867: movdqa %xmm0,0x10(%rdx) 2.49 : 7386c: movdqa %xmm0,0x20(%rdx) 9.95 : 73871: movdqa %xmm0,0x30(%rdx) 40.30 : 73876: movdqa %xmm0,0x40(%rdx) 1.00 : 7387b: movdqa %xmm0,0x50(%rdx) 6.47 : 73880: movdqa %xmm0,0x60(%rdx) 6.47 : 73885: movdqa %xmm0,0x70(%rdx) : save_128_aligned ((__m128i*)(d + 64), xmm_def); : save_128_aligned ((__m128i*)(d + 80), xmm_def); : save_128_aligned ((__m128i*)(d + 96), xmm_def); : save_128_aligned ((__m128i*)(d + 112), xmm_def);
まあこれが遅い。
なんか
http://en.wikipedia.org/wiki/Exynos_%28system_on_chip%29 : Dual Channel らしい
http://northwood.blog60.fc2.com/blog-entry-6827.html : single channel らしい
という違いが出てる気がする。いや倍以上違ってね?まあ伝統的にAMDのメモコンは理論値の3-4割ぐらいしか出ないからな…あとで実測しよう。
cairo 解析 -t 3
static void clear_alpha() { cairo_t *c = cairo_create(s0); cairo_set_source_rgba(c, 0, 0, 1, 0.01); cairo_rectangle(c, 0, 0, width, height); cairo_fill(c); cairo_destroy(c); }
A15 | Jaguar |
5625.562500 | 7033.187500 |
sse2_composite_over_n_8888 が遅い。
ARMのはなんかperfがうまく動かなくて取れないがまあ一緒だとしたら neon_composite_over_n_8888かな…これasm手書きか…というかソフトウェアパイプライニングしてるように見えるな。
まあわかった。 (わかってない。あんま信頼性無いので信用しないように)
A15 の実装は、32byteで
vmull.u8 q8, d24, d4 vmull.u8 q9, d24, d5 vmull.u8 q10, d24, d6 vmull.u8 q11, d24, d7 vrshr.u16 q14, q8, #8 vrshr.u16 q15, q9, #8 vrshr.u16 q2, q10, #8 vrshr.u16 q3, q11, #8 vraddhn.u16 d28, q14, q8 vraddhn.u16 d29, q15, q9 vraddhn.u16 d30, q2, q10 vraddhn.u16 d31, q3, q11 vqadd.u8 q14, q0, q14 vqadd.u8 q15, q1, q15
x86の実装は、16byteで、
movdqu (%rdx),%xmm0 sub $0x4,%esi movdqa %xmm0,%xmm1 punpckhbw %xmm2,%xmm0 punpcklbw %xmm2,%xmm1 pmullw %xmm13,%xmm0 paddusw %xmm5,%xmm0 pmulhuw %xmm4,%xmm0 pmullw %xmm13,%xmm1 paddusb %xmm3,%xmm0 paddusw %xmm5,%xmm1 pmulhuw %xmm4,%xmm1 paddusb %xmm3,%xmm1 packuswb %xmm0,%xmm1 movdqa %xmm1,(%rdx)
こうか。なんかもっとA15のほう速くなってよさそうだよな。
まあNEON読めるようにならないといかんともしがたい。(前後のvzip/vuzpが何やってるかわからないと…)
うーんだめだなまた来週続き。(多分続かない)