From 352832d46301d61bc9f050f81e00f82b68aebe63 Mon Sep 17 00:00:00 2001 From: Armin Friedl Date: Sun, 19 Jun 2016 22:59:33 +0200 Subject: [PATCH] Kernels should work --- roofline/src/Makefile | 35 ++++++- roofline/src/aikern.c | 176 ++++++++++++++++++++++++++++------- roofline/src/roofline | Bin 13968 -> 18168 bytes roofline/src/roofline.c | 2 +- roofline/src/roofline_avx | Bin 0 -> 18168 bytes roofline/src/roofline_avxfma | Bin 0 -> 14072 bytes roofline/src/roofline_o3 | Bin 0 -> 18168 bytes roofline/src/roofline_o3avx | Bin 0 -> 18168 bytes 8 files changed, 176 insertions(+), 37 deletions(-) create mode 100755 roofline/src/roofline_avx create mode 100755 roofline/src/roofline_avxfma create mode 100755 roofline/src/roofline_o3 create mode 100755 roofline/src/roofline_o3avx diff --git a/roofline/src/Makefile b/roofline/src/Makefile index 6a0ad16..742bf38 100644 --- a/roofline/src/Makefile +++ b/roofline/src/Makefile @@ -1,14 +1,43 @@ -all: roofline aikern.a +all: roofline roofline_avx roofline_o3avx roofline_o3 roofline_avxfma roofline: roofline.c aikern.a gcc -Wall -Wextra -O3 -std=c99 -fopenmp $^ -o $@ +roofline_avx: roofline.c aikern_avx.a + gcc -Wall -Wextra -O3 -std=c99 -fopenmp $^ -o $@ + +roofline_o3avx: roofline.c aikern_o3avx.a + gcc -Wall -Wextra -O3 -std=c99 -fopenmp $^ -o $@ + +roofline_o3: roofline.c aikern_o3.a + gcc -Wall -Wextra -O3 -std=c99 -fopenmp $^ -o $@ + +roofline_avxfma: roofline.c aikern_avxfma.a + gcc -Wall -Wextra -O3 -std=c99 -fopenmp $^ -o $@ + aikern.a: aikern.c aikern.h - gcc -O3 -c -o aikern.o aikern.c + gcc -c -o aikern.o aikern.c ar rcs aikern.a aikern.o +aikern_avx.a: aikern.c aikern.h + gcc -mavx -c -o aikern_avx.o aikern.c + ar rcs aikern_avx.a aikern_avx.o + +aikern_o3.a: aikern.c aikern.h + gcc -O3 -c -o aikern_o3.o aikern.c + ar rcs aikern_o3.a aikern_o3.o + +aikern_o3avx.a: aikern.c aikern.h + gcc -O3 -mavx -c -o aikern_o3avx.o aikern.c + ar rcs aikern_o3avx.a aikern_o3avx.o + +# This is the only option that actually uses fma without optimizing the hell out of the kernel +aikern_avxfma.a: aikern.c aikern.h + gcc -O2 -mavx -mfma -c -o aikern_avxfma.o aikern.c + ar rcs aikern_avxfma.a aikern_avxfma.o + clean: - rm -f roofline + rm -f roofline roofline_avx roofline_o3avx roofline_o3 roofline_avxfma rm -f *.o rm -f *.a rm -f *.so diff --git a/roofline/src/aikern.c b/roofline/src/aikern.c index 933ea6a..64e5c59 100644 --- a/roofline/src/aikern.c +++ b/roofline/src/aikern.c @@ -2,61 +2,171 @@ void kernel_1_16_simple(double* a, double* b, double* c, size_t size) { - // volatile to prevent compiler from optimizing this away - // register to advise compiler to put this in register - volatile double tmp = 0.1; - #pragma omp parallel for for(size_t i=0; i AI = 1/16 */ - tmp = a[i] * b[i]; + /* + COMM: 1 reads, 1 write = 16 bytes + COMP: 1 FLOP + -> AI = 1/16 + */ + a[i] = a[i] * a[i]; } } void kernel_1_16_fuseaware(double* a, double* b, double* c, size_t size) { + /* === Warning === + This is dangerous if FMA is not used/can't be used. Then there + are intermediary writes (and reads) to the stack. With FMA: + + vmovsd xmm0,QWORD PTR [rdi+rax*8] # 1 read + vmovsd xmm1,QWORD PTR [rdx+rax*8] # 1 read + vfmadd132sd xmm0,xmm1,QWORD PTR [rsi+rax*8] # 2 FLOPs + 1 read + vmovsd QWORD PTR [rdi+rax*8],xmm0 # 1 write + */ + #pragma omp parallel for for(size_t i=0; i AI = 2/32 = 1/16 */ + /* + COMM: 3 reads, 1 write = 32 bytes + COMP: 2 FLOP + -> AI = 2/32 = 1/16 + */ a[i] = a[i] * b[i] + c[i]; } } void kernel_8_1_simple(double* a, double* b, double* c, size_t size) { + /* === Warning === + Seems correct with -O3. Though -O3 does some loop unrolling. + + With -O0 this is dangerous, intermediary values stored on stack + who knows if they survive in cache -> unpredictable. + + With AVX and -O2 (not necessarily FMA) best results + (obviously correct, only register shuffling). With FMA: + + vmovsd xmm1,QWORD PTR [rdi] # 1 read + vmulsd xmm0,xmm1,xmm1 # 1 FLOP+register shuffling + vmulsd xmm0,xmm0,xmm1 # 15x 1 FLOP+register shuffling + # [...] + vmovsd QWORD PTR [rdi-0x8],xmm0 # 1 write + */ + + #pragma omp parallel for + for(size_t i=0; i AI = 8 + */ + a[i] = a[i] * a[i] * a[i] * + a[i] * a[i] * a[i] * + a[i] * a[i] * a[i] * + a[i] * a[i] * a[i] * + a[i] * a[i] * a[i] * + a[i] * a[i]; + } +} + +void kernel_8_1_fuseaware(double* a, double* b, double* c, size_t size) +{ + /* + With FMA (and -O2): + + vmovsd xmm0,QWORD PTR [rdi] # 1 read + vfmadd132sd xmm0,xmm0,xmm0 # 8x 2 FLOPs+register shuffling + vmovsd QWORD PTR [rdi-0x8],xmm0 # 1 write + */ + + #pragma omp parallel for + for(size_t i=0; i AI = 8 + */ + a[i] = a[i] * a[i] + a[i]; + a[i] = a[i] * a[i] + a[i]; + a[i] = a[i] * a[i] + a[i]; + a[i] = a[i] * a[i] + a[i]; + a[i] = a[i] * a[i] + a[i]; + a[i] = a[i] * a[i] + a[i]; + a[i] = a[i] * a[i] + a[i]; + a[i] = a[i] * a[i] + a[i]; + } +} + +void kernel_1_8_vo(double* a, double* b, double* c, size_t size) +{ + double tmp=0.0; + for(size_t i=0; i AI = 1/16 + */ + tmp = a[i] * b[i]; + } +} + +void kernel_8_1_simple_dangerous(double* a, double* b, double* c, size_t size) +{ + /* === Problem == + Same as for kernel_1_16_simple_dangerous + */ + // volatile to prevent compiler from optimizing this away // register to advise compiler to put this in register volatile register double tmp = 0.1; #pragma omp parallel for for(size_t i=0; i AI = 8 */ + /* + COMM: 1 read + COMP: 8 FLOP + -> AI = 8 + */ tmp = a[i] * a[i] * a[i] * a[i] * a[i] * a[i] * a[i] * a[i]; } } - -void kernel_8_1_fuseaware(double* a, double* b, double* c, size_t size) -{ - // volatile to prevent compiler from optimizing this away - // register to advise compiler to put this in register - register volatile double tmp = 0.1; - - #pragma omp parallel for - for(size_t i=0; i AI = 8 */ - tmp = a[i]; - tmp = tmp * tmp + tmp; - tmp = tmp * tmp + tmp; - tmp = tmp * tmp + tmp; - tmp = tmp * tmp + tmp; - } -} - -void kernel_1_8_vo(double* a, double* b, double* c, size_t size) -{ - volatile double tmp=0.0; - for(size_t i=0; iUwvcU7`VmTLKI9S-2MD;?67BEK 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 delta 4539 zcmbtYeQ*=U72i9_Mm9z#*q0huKpvwn}LjoTt z=Cbsl(<2yW^Q2LmhtHKBFKH}H!;OW0F)(Or8fLBhq*U*`*J7dk|nd3n*fQ?G4(u;YO2mAz_6Ot6@aIgp(}cI1@H`WKK;@Tho^Za(v^~)s8SytE(^}5j&ZKoxvo1lDD*FVzGQp1# z@taAQ=ue@QT_m20m*^Gz1>$Amqk=zAyoLDR3H~(kRJ+6>!M{O#n2MHY7r=1>s91?z zf`65GDpF#r;9n-5HgX~)_=Ch#O%nBj-%mW%BH4EDiH=W;UmA{pF| zIrp*m4U{YX)JS{tg*`fRrih;*gO8HIrDSl?{S7`u1|Jw{@EWQ-GGZ^;+er4l_&4kg zVxtXruvnzYG(>}pM9KiGD?Q$yKM>kNRWuuH<7Jy-<5 zO_Y#Mj`vz!Ti@dvO4ahoK>g~v?r0QdwC-5FAl?3K`1B%ty4j>msDb0Jt0C5)RU8G; zT9S6H?bD}f%L=z zyXJ4mRTqCGQJ2I%P7p|rH;wDN03F@$~ql$B#S@csK}+$3b;(C6`Qm8 zuNYXu*?Qmku38;Ic+MaVbJi*fBj`2tl zaBDXXoV819iAtI;CJt6|=Vv!Wj)zi=SxW22$h{U>u$rviKx;s3>hlc?sTrgv7H}7)7XVj9M_2J9;wnI)<476Y9x7{S*~a; z-8Rja#Ku9Q*Zh|UM>DzePgI1V62N|O(qgh7cCIT;Dy_djw!}7v!l?8D2#X8=fD7o; zW7HgrBFIL)%KxW4{67~^_H4mnqeHd}PKwNQ!xu3|igpwarC4{I9E_%&-1~q%d6_^lIz5o=WwC#{Y>+5j(BfyRF0w|@B9K%xuN6JB2ja~fg31WB_k9Lb6ELkDDll*dt zM^0Yj*%LisnzRl^RNNgiFgDs$40Zt5fV*fBdAZ&3Q#oLFKWnMAt1VXfXJ_p0K$qRI z=xsaRePrh_^yVPi2Ezy_;eQ0a3;4+q_`4D-V&zDO*CeRH_$nsU-{!fK7G=#uCMaVv z-!SPFK2Q;weinBgwF1%8r$b1LigX^%h*qf6WHH}8Ei9>Au1v|E5bu-5b-1hCmat(+ z*Av8oQupc$496YJ_{CTh9Rzc-Fez;oFc z7IpDgtCu>4MT7Ihw^>}$dFtyvf~ErzA0DAY=k|UdbzkZDfUa-sp-jGSw#z#adoY*T z*~kq;rfoMS8Nr{x)Kp=2&R{-R+AvifBc^$;MgNxY z;X~*P%Gm5=DMUA)K9DvI{325@|z8?mB1<2{c6Yg zxm{Anv3ajc9nA~;QpX<_mRRK7WBA2I)3S|vpLOxv#nsuyz0m98s}@%~jqAYpH=>ol zw7Ak~Tn7F6_46bC_r+CN`hmc|8o4#I4GtI6DsaZ3_wfC9IsDUc0i1rolM{Gu?d&Wg z4Juz%JKNa)htzarR{rqJJbtXU*ibvH@(Z;KZMt}>5KmoFhKq33l7(3%=~=xtesD>3 P_R%S6c9WG~T -s \n"); + fprintf(stderr, "USAGE: ./roofline -s -r \n"); bail_out(NULL); } diff --git a/roofline/src/roofline_avx b/roofline/src/roofline_avx new file mode 100755 index 0000000000000000000000000000000000000000..4f798b1e22e81f0885b55b1cf2603863cc9c4e31 GIT binary patch literal 18168 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 K%&Wls{QnmUp}~6q literal 0 HcmV?d00001 diff --git a/roofline/src/roofline_o3 b/roofline/src/roofline_o3 new file mode 100755 index 0000000000000000000000000000000000000000..8dd3a95ae6947b09a7228f5c9dbbda21d0cfb038 GIT binary patch literal 18168 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 LKS*o9^z#1?@%)Hy literal 0 HcmV?d00001