From b81a0228a29d1515be8b41b83cb5bdd1d0f85c28 Mon Sep 17 00:00:00 2001 From: Daniel Molka Date: Mon, 28 Nov 2016 10:03:04 +0100 Subject: [PATCH] updated to version 1.5 --- CHANGELOG | 4 + FIRESTARTER | Bin 365503 -> 381888 bytes FIRESTARTER_CUDA | Bin 371121 -> 387208 bytes LICENSE | 55 ----- Makefile | 11 +- README | 10 +- avx512_functions.c | 530 +++++++++++++++++++++++++++++++++++++++++++ avx_functions.c | 192 ++++++++++++---- cpu.h | 1 + firestarter_global.h | 13 +- fma4_functions.c | 52 +++-- fma_functions.c | 312 ++++++++++++++++++------- generic.c | 114 +++++----- help.c | 9 +- main.c | 334 +++++++++++++++++++-------- sse2_functions.c | 192 ++++++++++++---- work.c | 71 +++--- work.h | 157 +++++++------ x86.c | 43 +++- 19 files changed, 1589 insertions(+), 511 deletions(-) create mode 100644 avx512_functions.c diff --git a/CHANGELOG b/CHANGELOG index 70c9bf81..f26e56ee 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,10 @@ # Contact: daniel.hackenberg@tu-dresden.de ############################################################################### +Version 1.5 + - added Knights Landing support (AVX512F) + - added error handling for restricted cpu sets for --bind and --threads options + Version 1.4 - added support for Skylake-H (FMA) - added support for Broadwell-E/EP (FMA) diff --git a/FIRESTARTER b/FIRESTARTER index 22cba54dd5e6bc7bf78aa0b53065aeea5529d8fb..1136c093c4d5586d9aa489e33dc04d6585fc9625 100644 GIT binary patch literal 381888 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�lo{Iii&S7}Q!0rHrfnvI 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
*RKM&^ zlYFU@J=9(CgXXjsMTKGR1|F^}#E~GcE6Y0%cM0)GZ zBE4<9Nbh)v(&3p~tZGiLi-~kwT%cEaif02I7+R=VX`Zv?| zJl;6(@Qz3Kr1x7p9(^FaAvSFfaL=E2Jo-QB=Rx^tIs*zL+Pg>72T{yT>4&H7*-tku z`EGg?rTlk#39^vN*sS z4(?$)DPVg0chmJ?FuLi0;vTc}_l@%&*de<%hk3a}5A6IS#yH(1x;B@2QZgJvZ^2b3xSve# zlgcQB;BxcAsy%LAShdH^3##^@rr}<--=1z%c2KIlThhM@FSs|QA6FnEI9&N;`UzQ+ zt8ZDqx+H@KxwCm81-G4>7Z$E?^SCBg^PEFZpeYAjkw^|I0!U5(f?Lvi!wc?B>EA09 zQP|=t!Tn_VNm-MTdpRZ-wjIq2E4bV|fg+sE<9>39hQs78;pTBouI4$o*Pe@4@^B9- z0&yXTZ>v%fE}JG)IX4eb>7np~%k2#-xVNN#9UiZ6^MVSlf>YeQuxgK+$2A2|dnTw1 zc1C_iNH2|MaD-&!;NCOS`sl;FmIvr$!$^gb#*A;dql7W24 znMkx3>$*y~aLTOqO6_MDS5CQRS0hJ*Bp0gz%d_qbBRJ>+jF;}pDK{VxGsa=3gV@;< z)6AjVG$T|#3Rg~*+|N*8FJ}P;Or>$%nM*12?5Zn%;WW4}-Gx&n@-viLDaK2?dr!Jc z&#nr|IGR>Ysj*jTN5dV!a4uiT!#!vb|JAm+3%z;9V8X7P0x}9Qp>ZUR2Hc7e>&{G2 z8SQVzDy#dGxHD8b3!vV�?a|JNO?5Z<>;aIe{Byu!l zTr`xMW`fFKCpM6TUGc~ZyTZ;y@_dV!W^necBRJ*Qp%H#Uql|ur8L#Bwo=Yk7?5Zn% z;f(C@29lsF9+liOkmto9uNh)j4Ajb^*q? zZP6&Vqe0G|T!@~>(QpSaoXb~uzQvz=&>~l0b~VVxG)A74-l1U@+)xu5N8)Ipx3T>u zsM<3^Wo~cK$euE|<=>&91b0IC8PaCtsy*l4)tAH;jfv`LD7})$O>+e>cy`qlz;G_W zm=HTOCV-<6&P_8xWgxkS!moHN{|*g>SBhCV1?3rHLPM#&QhRAGrOdOd#?3)T;e-Z8 z=QvFVE%{g8@gVlDI%W(aM}v+{D6N|YE#kY{b{w{Xzf>I!C?o9i59+3wpz@NV#?K&U zuS|Z1v>86fhlq7@ymwVDz&N%Y4W8K()6Ah94HaL>!#!63BmV-7$kC99Ae5VCg39gV zwiWy(>}R;+7aT;C(Vslrb17w>U3JCIcy`sft}AR@l;>N*!j(KbG~DqE_MM!~3maY; zzv-awrsHaMRZ2$WXvme`rFPRWrhQl2`fN;#4(yV6C6t>62Kz!~C{Ju42^!f`2A6?+ zSiwCCH`2RiR~=IZ(ToP|1rFh8sQ5~r`5;#SgJ)M=0SpfQJCS_Y1sJ8?p`oJ6p;k`0 z0YShC4YQ*W%1tvtWgt0hAQ38p*X#v4X)n)_Q*J=u#4C(E!{U`kH=J@VU&-U9VN3_zn8uD#*dsE_>}WW~UZ@F; zBXKmAgmTl2Q2D6wGk9X}7ktuQo(T;%nsPv8uoD|df_iDr_noLWLo|+zHeNGoS$Knl z{k{|RDhbCcCmioP(XW@#uc5$GG(LYky?bklIcMq_ALjQ`*x$kDcKsQ_n%lVGhEn$r}Dc)y*@?1M+GlC*{<`-m!04( zC;8uX;*%lFt4>aPt!P}4uR3Wva5yp3;=hymZ_{y{tUaESb%NM+0{`lt!pY{Bw_Sm| z;wN&FIEj;{T29tZQWau&LY zK8@cKDZYJw;c4RgHhcWG{poPxj?1d*r=I?5etQc4eypwSFNr%IWC3Nu{Sz$b&XYg;m7p)lmqv_j4XJhcp~ho^Pv0 z$@@fAA42YfoCVAwcebq>lu_m}m_trxTN@}pW(u0aRs9K+X3;NC;si}*`d(%+8p9P) z4$)K39Z647ztoF<85Pe&EdDVw6pi7kh$4FG{@^`D1*b*9`{|iPhr4@fJ_cUoI8>vR72aUBpbsz~Mnb6jM(<6t1T(68%E!e7Ilk<9@-g;fknVOg$yu zl;|T<2k-<}R0+}Im+AzPseC>4tf{A{UoeR2-p52$^tF&o%|{-0Pdx(462Xbbi4(-& zAG3_z$CC<7C?ruq`iXiMyrHbm^I0oxAL7Q4jQv7XRSiNAi7M1n)D7UxpHSRmqAL2j zpC$A6qADVkPWzFD#K57s67G?`tPlSvs#;CWVCe{>{RVK?l@5(gd>ds^fVSa^h$4FG z&qvZz)GrWlDs4XruNVT)b5&5qT-Aqg@gQr%J;8g5df`2y7w!`(iJ0yuQ)HIFo5x`d zrBJnj^4s7&MZyqF`}z0OW5Iih`X%Gg=<}I1RIFR~kx|O+si#ambtJlvs>+o1nplIT8{_*ZhlkM5$Qf>KT+?(F04j< zc#)$rL631&zY$f@weY%+#=Kjms2ji=y6|IB6@9&r_2KVCRYY*(38Fk!z)DfUe%g=v zE*DUUmmC}LM3A0pcW89#CqL-77*#)WBt1p_0s$x9-$z42Km$MMM^!x-yr-yOKjcTu za?2D^+|chVQ1%AzDe9MC+K;Nr?J4nw*uXuNi_w+tQxawBsePuNIuhMSQg)dOq%Q{L zIa5zjRT#w7;m-?=J|AD*c!Gq%EmK5sgY-v0k*N4-g*o=Jj6J|7b+P;vk|-+H&q_J_ ziBuizLN&EXfTT8VOdFo^SE4GCjvx}1tNZMpBD-}!@P>+e-U<9hM!aaXElAa=|gMfbs1#fjQu@#h z(&;XVirH^ljo+i(b3fy0eb!BdB#LhGvr^7}qTYpFpsX&pmxlh&MOE{0ExhidesRkb zbpv?A9p-d!l8NBR`@jE0s_CVc_Th#eM7;{XtaqCsdUWqpNPxTa8GP|dqH1*Vx=suD%sA4@Ro@e$wW9lhl z7ECxXdQ^Z+`s&6LL~+X$QQRQ?5l|#5=13gn*w0n}AFs;c8VccwYTRV9QmUUw)xj?O z30YlkZyTQb*P<%A7GC%L40pN1v(ydX4R@HpWAydMtPdX*RT1Gn4nANIv)e|LVznRj z9R>~u$mVl%NXnkD8CVGU5!c;4Mg1aCF>7?n;RpSwqUY_3!uJ$uLkM^q$}iydQcpb) zyr-zcfr|fxf?dc@$rR~FV!9uoSd6NE6}+dY!-Hu*|DJl-W?-S7qJGK6=#QYiZrw)| zz)(kU_AF4IwkvY?)RE{uVkkzjBRty%%3n-9Mg0O3PW`f9fK2WpALN&}r}Vt#$@bI> z&0Es^j6G?oCTbkBIheGBI@ME?YacH>HK}GM>o2LlxPByCzox!r`SmmYUq{SZlem61 zrOk~a&oz!bu)OZE#I=8zoESY^v+rF`9Lgp>^2fp0ykDvNmybNTeB`;MC?R|5-o&+c zS0&DWYUs(twL2zX_Wt_!)xW>~^7`c6j`^cM-)+w&O+6!SB}V>~7cZW3%UP%@tD3(JSZDVS^tGSe-anM??d-GYM=F!)8?Xl2D8t#A;mp|`sf}q+>HA=+ zhw{?@86EVub0Bra*_rm%?sV_^%d*e1lyBsn!mWlkU;kxV*u>!Pag^wKBKJghuLS#M--B z2U^<)Qv>PDV7fgc+DrYK9!#|l4pG6e*o@2+E_P$8x1(=>DB`2&y13cBtv%EfjE+lS?yGrGHnVk;6KV0KxQ zBQwWFowTB((pMR+Ru%(h}{MOVkDpJUX~^oM&ohW@nZ&wT!S4*jLxCK7eG zNX12Tcue+ojJlit;EL?%7mE;NR}qcO}0!8MC{5hDhX{KPt$ z6_!l+q6HabPFMpF%S^hjmviFDX`J|ta}*@Tx0Y86L#MNEpr^IBJ!SRxZAuMfS~s$w z6u6%nezukF?MQ7F@*Sf}@dFld-PUsYi)Xh6hx=33n%;D0I@Mv#$bd&y zj9E0x%A`M#vNp92XOexL$yVs4_H^rDdSiNU*qRlyX5&gMlNyZKSHQNuuG9dHizHN1 zD#<0p77q`mV(rv=B4(@%26U<;3C<*YTKiE}YIA${P$s=G6$4*lAc!2X)}B6$Inh?G z&*~iN?jE*UAP*^PY3pFC)!3UE92jaJq@M8BV>Jv6kSr`sL3nylb!_pPWy=~?H#few zVMW6V^l!R5)qx=^^VN5E_qF2*`+7+ah;lJ-V?Dzis46+AZ-~XvT9$^G6kB`T&yKaQ z+(T4i14F%;7)o2xv?fLpGAl-UfUcx_bCd`AQMRM8H$9k!PXB;zi&7=3#ZzLf8`1dI zw(eA{yRWrlcIQwp^8n)-pIEGMDTe!1v6b~J8t}#Rxyn%tnmO2&&Pe4*rBFGukMN_k zt|)KWnw3kE7p+{LT-&f}WmBRtDMU57pvBZerdtsE*o*~p7G&^9Gv=H#m(t-BYdkNx zw{Hq-e6En|YrbfCa>=UI4UI`Cgyg&eRn4axeeRoI;J$P8eTn8vLe#gwa9^SN&UM{K z{A_3n^nmB7=c9Hy?kiN`+o&t4QhWq|RxXy$i3FL_%lT+u4PgS#pcCkp2ZL2E9__0#Rxv62}TJGFe|pHE8X4| zgZ}C58+2fYwqazUtD;(8XSdc4Y{#Pyu( zUr))O=R9XU4y7~i$QYM14&G*{=LjDtr=EqXo@S2{boLL1_K}Xa^Zn~_KTZkinK##2 zkwaU$J1A^TIeeR^6$3HOQO}V*QEok2A>?RpXAhBn4cSEoeWw+Jr#|;{m99RmAabom z2_7()pIT9P>nq6v=GLbbhL2TpJ|G#Y@I9#N8|vNA+qbDVrqDBj9ON0p|45|(eHml3 zOJbw#bVr6w5RZfVI^&#X+eCUnyGXB;>33!NyiCvS5Z5y@yBndg$g&d1^+}uWfAg*-8 zq+uUy&1@haaTK z{HE?yYX;6^dNbcSyZ7wbvsI&82i6buq?P|QjmJUH9|yST)L;fJ4H_d z?rlmBcJZSMKFij24)pafbyc%qyoWFPK?<=#wlCeg5ngBq`k<$+uRB9dD?M#D;!q-h zB=corU9B17FIxG|3u1FAA73;d)R&dW_f?1yY>B@eM9J` z-adHcDRzlzWS$8Y$o2*F>ti$L)lE@RNQ*x5{!IfEhHyvRNK1%-rNXiuu_@{X((`U0 zi`HD2>P3_{)rb!4w(5s43VRXGt6#CyvK-=z2tfz%ZY%niVj&0>sDVrYM+zUHC|lkI ze5QfNh#I1acpL6>Ha2z^Q21H1Vr@fugzDfNaS3=@HvsyyP+@@Bc?%0$9w2V;^6ED>AfaF4HFgL)CMC+Q&JSk}0@p}D1gH9W90 zWuz3*k0o8H_6_9!{0(Bgu}!JA45Gf=#Y6pwN~Kr_+Vzt?EW{v~)WFZ9AI5gUGOYZ4 z+_aKCjx7&hrw&|~mxUw-cD*9Jr(uEFl|}Fq9p2sDh8YvB-Vv>mAF`-q_n??qG4~^q z-$T(zpbK3(6zAZ;aI6m+VL(F>?pH0Ae(mu=M&8!sz2ECvdT%bo5BL3uHsrD*Z~b1^ z>B#O6U%v;bBQTir0D0T*x!D4R4~5+YD7M>4 zcEqQV%^QZhTQ>k(BSIu9b2To+{qu{uKhc`ml0$G1s#IgA5*7_>6g)e6*| zx3`@9DO`?kLxfm5_*|fzJiMWz0zX%Q0c4lMxWb1&i!mS9(f0u|X#OJ2Pezz`pcm8K zQX%%F;S)ed5!RjEPr7VInvm${H^w>t|7~)oi#)%**G>0%^Lc*XUMN-dzyIUn{+s_+ zr0@HnNKfA)()(q)?HciW`G-V0`C5_gkm;5Wi{J0~h)560^jjYlzxzKX(plGube~MW zJR*L#cWvBsMe9Ik+oJTM!A0GR`WN*s>RGg&=VmQ@q!{RMLJVp+=89U_Za+s$2K&~h z2p-bS_{jTV{!@K$>iB=BN-xJ}(hGsb~#lJx)@r2B&0q1x3) zp_blZxUmxMX3pdma2yDLem%$#{vN;%j%3s?ZeF!~O-sY_OJgfn#V)B|y}Ev7%cXB; zH>V>th?#Eqw?nFXTagfP}D=IXGFX~FDMg%qWL zkBkV$KpOrqqAG(^5IlhXYEKQIB1EqGfS+g$K<4c}b+*6R*{C_z6vtW)6ih2#(911q z1%O0IaM=bJ?@?$g)1Jh#n!#3a4bHq+31sI{7c2|UOnnT(ocUOgkfOF_Vlx?awGX#< zr!sXMjHF;4Vq1g+(YGA9>+ee==H+OeEabvv%U3nY@Q`KS*TaAgF}L21P3exoE|q)n z*}#0(jn~JS(@#nHGNoS(n9p?o(MBKMD){z}Pl)sa`Mc0_E|>YPH{`!hmZ!=&=*jm^ z*$+=h`n{g(L!SFDlh^-7rtN+G!vo|_SXi>tZ^Z(=_Z-Vm6PTOBi7l) zXfY)gz&1DVpZWav9Quppb^HU%>tu?H1oUZr0KPRe$E+o57t)`3=f&juO3oqjVO3?! z5-a+Ur)dq=9;t)$+usd8wgT9^lM z+?Vp+7vupP_vh3bpyA8si%P-l48_w~W{EFynP5zmFLTWb);9s}FZgH$>JRd0=lDIE zyIh&Y_*|~ViFSZKhd(*x_&lGvtXzKOlxKQgW1(tXIOU7iQaT4&Y(=_#ps$an;lfr> zs`9-ODar+_oef_?3rg)y3forV?~#=2Y-5me!gPL-}_cZzTj?N=76|QKf*r z13DkwDLgbyvf0(zAz~Z|$vSF|&7>V#!`P1TB}$&S!d;kMv5 z>^Gt5c?6g;sqRiVE~(Dep>8ak!EB(c3C-$`Enij7Od=MMn|y&H(BtybC@=)7r5(#f zXpDnJU2x5rN5mS=K6A#5x><#rCEF02H+Sx=m{{9`zeCs!g+)8>xImPJl&%*pO?vtW z;bBIN7ASRKHwqkf>cN3j4}xhF08bvYTrgsC z6gR}G2=14{Y~zQcfG^esFw6S8uy{?Zd2{!3;j-+Jz+CFY`XVv#y9?i|x{YLh(*VMc zXig`sRFKQdX2SuPjg@{Jng++Q_-oagm9!0pI4(Q?0!51{X{O${H&e=Ngyb-2F z>`1qwjjN+*l3eFmxGY*Jmu^oFVjH7qRT{&{(5~5Sv?^_RW3x~URL=#9ASAGx;teV~ zOe@O@H$W92tkI&_S(|4K&-wrs-JFGGaWXlZb`qWyKr+No8K!tSTIbjjhQ4V-=M`>_ zk+;3huADMuO2g(>T4acwnp5VS?NE5c2=8Y$j85yoV8&&{DVk5S5lX?iOMwzTXYO2A zLAsRI*ts#NObW?Uq~Em4c&6{&BmRxEhK#iMABx;=4 zAL9a!q#E>uM~BkTU48wuCW%(9VqKY3;gEg+-dR&uFT4it;T{mS#!|EjoOySfoZd~5jaw*M8Eo*F9+0fh^TefO-3`;|>%&l?Bn&tJY zV@+#TH?3-Jm=lXNWAX-4I_1KZYhnmxV#=gD)-==xQI0Lg4)|VL;fs=ZNwS<3l1r{= znN)NwJF*A;J`vAw$JNYWlIXO27(p!BbkhX^AKI&LAyTmXlOyRbwa3r->!u z@8}vF>|b>D*_$?PnzO!lXine2`m@nIYFg&(ciQW}rg-`9nwVM?qe&@R7Ur3WB3*kn zKVb)O(G>KHn3^KhMFx=9(9#d{gU}kLe&SiC3ybA%X^DZ#)BZpd!rdbpzYz`|#lN=gvEC_PlxcM+o0J;%8HL zt8)!v&4aWaIM#xhr`VdobT{@A&x&0v7eUTQ&zX^?g|%%%>26+$F9ZHd)O#)kE3XBz*b$q3koDJ%==b z-`9WRP<9>CKOo(Vbk4sW%5Fot6X~r;ulbKd*?W-o-F7JZ5Yms|eke;v)qf7@=}2Gw zpNFz@k*@yMp==Y<%}BeDKJ{NH2k8&LjdGAa@*R|ebp3Y^W%nWd(vCyfX~$Vs?@rv0 z^j$x~{YX2Ib|D=>x&`T}yAEY9a@|B7NZ}hq7yt zuD$nAwjb%WKSeu`e(iq`Wp6`z!T%k~?nZhL=`%GH>LKhhQ)&v6jxnm?fa6D;dtq;rv;@MqMI^y25iPo!6k9m?K_ zbj=xK**lPKfAd)O=SY{&9Lqj~^ovNRp|{^wH_bTZ>723bL8P4vP~OWeYu9;W*||tZ-Zqv^AYHK#BE_ViU`tDe^3+dPIL_3gP`si5pHl)438_V8<^xpGc z$R0%c@Y`OZbmx)cZaigAie6b!`aiB6ye;xi$hOECu=ApztKgJraQT~Hpgp5HaShdrZ)t>(DsW0C&d5iU~*S!5L z=S)8fRK9;H(yyT0&k`XGLHgT9#P@ z)y%7QwqrT2ANu!0**A&%Vy(DHeCz;yGIV7Isa0P)?b>QIvZlMLc3Qo%_O^ zxc+-wpF!7`*2dQ1D$zSYf7U~%@~#5CYWtz=R?2^2?ah;_uhr$z^)KLhH?F7j_4m83 ze;?Ox&vXA?Tz}o@q3kAc|80}1`}Fyt??n3YzI%0T6|fc^#8u=n9RkDp6KKX!xu5a@3e{TQ!#lkO&#wNK#sQ?Pk& zM!Rrdf6ZBXc=7db;QF6n>plhBgnDFdp|>$7nElAj&Qo}#Z$aa~`I>y7sv%Ko#s4mtgt z>v}h?-*Z3YUf;jSb^Q~#{^SFPvQ^Yhmao5R22lIHf$Kl{`JwFp=#yN!a#Tw5ze-_tU9`dh;`tMX=kaHhBlqG${{r9oj$yEL<(EkW4vGfAEjc6XN>Znls(kKaJ~q4;;$=;*Gc;?T z+n(Emfwd zJzl81y|_LJ80tUOeg7ux&$FQa6X^E{`Z`i`^gJg*u2uqTwUYc@Si7yN=2BOAvvB=} zw~l4+Qsw=(C~qm~=g%6;?ojj}O8W=;W1!!r=wBE041#|3?6K?|(SQ9lb$0(zJ3fu; zThGOFiE)1O%WBThwmjwEV~|<2hZ_LRn7Ze zUVE^rp>|94<@i9xKYlE29LqLoc}}?Q ze;=+7zI!bDL4AFb>-tr=e&0o7*|+HHXSuF_0oQ-Md@TDMRmk=4ch&!WT>s{Zv23Tl z|8m#;dvX1*E61`ObiWv%ZK{CjAiaR=7pxk~-a>qo^1QC*^VME?o(?Sj?e_q4BAdu} zxhjV3`%-!RWLG&;T;_)zSZXU}L@6?Cr9|rwPpkF{l=!?xLo$`DE^m{=65tR%3 zSY7i2-OqI2_i?=!7<@jy(|tX-kLdSs=DuOa@*&n%=1K>y_>W7*+m{8(H&?fUA)wWoigroJ|I?WCH%=GxOiTZ}U3L-o>m zRd4+ISoU;JIad+=8)MmjpNUM~a=tt>r<`vf|1I~AWnbwjX9wv2^uSp5^3^`&w5-l4 z=UL>x_suWllyf5R(f`bRA$!7Ge9Fnz<&;Bs>W+r+-T;Is$&-;-7=gGs_iyh^>1Gf%> zep>6{>=y<^IXBSw`Ma9MwXy3bEv}vUiI>&a&b{`ynvW0E&IAqDJmcwGxPRcj!`XLx z%Dor#FW-MSd+wsV<-T!|q1+SU2;5ZrVz${+?sU-apZa2U^?UP{8-K5%+z#CTc>2Zc zg`RS+0{xX6Ud;Y!cHVLynr$fe`?!DCjk)c;AN1-|Pq}1AUkBg6>uXuzf7pC%(Bm{wJNKi!1X5OE;l zK*WKF14ji1nqC#>=a?%~^-#)X_on|MGbs8`f@xt5~eM{+AcCeU#Nq8|oJD+2h;xdm1ODu;j&q7oB7bg` z&OJhH{5f5wuav1uD5TGyZK8cDCa_jkL~#N7AcW7KSIKndNpb$B=(n9HeyetGmiZ9k z<&UcW#jJRqxiWuN{#NaHM*hC_<#BoE_#~76PCUQ2wr|UR{gF%`lEkkePNv7bQr0iiH_7xonJ$y*#WL-b=|-7; zRHmPm=~ra>ZJGW^rVq;WahX0R)8kH)^~>~4GCfbGR)LR_Ybu4l-~3TQ;kg?8Zd%=d zzqua@5z^q=G+d{UHhr!(TyGVZt!w3V#Ro~Y z((=nE4A*<*^-mkFx5?`_8Lkh?>$e!LcgyQvFVE?KfDHgioIjsqErojYg2 zoVl~l8{%K{{&wDZbLQd&NOgja^~dwhn|t2e^9vPeVS3V9SRK#FSA%y`wfNF&tU+J; zB(2|_h1EdY@Al0PtuOVzJOA;PpWdv2wNd)ko&N+&>1{WCily|soBnc3**Q1;MC)d$ z2i^3OthkT-)mXLG7GL^QOW93#In%7$q&;=hPqwyf$d$_)>lABkpCA1dma@a{a!%Fu z*G-4D^sx&y)@hcXy{NHXWgWaB*N)U!uzu3My32pH_0T8%^1sG<=u>`lg&youNM0vd z2eLLrd?Q>^W#zV?@JKcIf18K@R5H<@@zCc;x)&$Wd_)z{%j8dsb}GF=Q?ON-WmR|v zKl$?k{H5|0?viBdqxe!~<@U?JfbREP|H1iRW5r~>D3m|nR`kzGzDfG`6#Yg)pCqzd z_e%P75B+gTpXs3!gXwu^dFZs3kDhCz#F3wq<D`jPSms|Q z>HjY2svMg8qjDNvEz03Fhqxy#=~b^4^!>6NTGL1QpO$o9Ylv%COZt@8i~I_w(i%NK zKGWJiD(8VqME+06@}D?a&|B9EI}?BbN(0uQdYwE0X?To1pU=BhbGo=`VB& zIr<==5A){=CS49p8m@f|5S# z9|T?D>I0JgSxKkyN1riCZ}>u-fAg9je4C1KN9A|_lc4`6U&Y#D(EZwfmdyXTdqsYQ z|KDoJKi@!K0y-AOTHAjn%AsHMStsd_O|KUO`S&A|zU9qs`WGer>nq*#U6LMukDLCO zq`%>dZu-j^(4#$HcGK%5{T)Ab(^rA+$DgFkAK&fHf2E{vdGlh|bN#cVf8ImCOVYpP zp+Ba|d5gQ8DpnM=)~t)&^cj-A%tNRB3B><(9{L7Jk6-F8=Q>G$|7~vize)Ng4}FiM zf6_z$i==P)rn{U|UMAY}=3lw#Z!THIn{24}G(wS8sLa{|8Cme!ZLi9ZBzg z+)e+Lq>p&$FG~7XJ@hl#F-H5JaF=s|r2oq+m%8}VD(QE5=pUB!hdlJJO8S=5-R10% z^p6g?=}$=dmpt^7*kP}=Mm_X-lD=iLyPTDhe#%$f^o*pR?V*28(pPxs-vixmT-_`4 zTVHdR|CFRxpV;8y+bJAisI|`U&=*Sj1s?k4p!?N(h0GtH>MsB9CH*@y-SqEC`u!ey z6=P=j%iX41Zi@;Bn4=#Nb2ZVC*)mxaJi=Qvx za&qx1op*Q&^xJ<*IaO<&=s-E5Z;|-CTK3Mcq|ezMXNuAiA7#4C^nWqb`yB)QUITrf zfqo&1{d40?*dy;rfIf}*>G9)M$^37W`F|qw-z&%STn|5c zYsGW@=5|p&uc5|0mvA}qW=FCCbn4%IvffGZ+6QI5H7nvw;XMoZ_K%YOD(M$|Nap`{ zNw0pl$j^HqaE;C~J;loP)9>c|@@7Z!f3ln(&J*R#kk|H0di^G$=XnhuuKh^%<9vy? z-!Ai?0EdP8clj4Zf2lRMXEI%8awHeX{8LX8sG34(t(4U4}_>J3Z4EaA}px+7o zKzeMNM~{7-^VeGMIxEht=RH;UcBi2nT1!cMs9GTMXZS7)8-D!T`6>gQ)=v68SG^o> zzw`9h#gblgzNlCEJDrmLmbVK!?*&4eh9&*OpAh(m*Q$d4DW>C#=kuSS)3{yek@p`M z^8eaEe}?I`)`m0VT*Ljco);wj_Dh5%;HWGP|KC8*(D)hK zDW0oS>aicna<)jkq}Hzf5_ICvGg6-@J-^>jehtg7WV$1Hos{c)n?$|5CkofkH{@S# zpkEGp%u%lT+9S)~ze?x_UVD#=Ba;5DrE$*6d&%(a5)6Lg!%x2?=(q7z=tIsge>jrc zK|i_r)z&^wKmI_Lf7RPWIq#GA(7szL|Ey07`e!8lK`I9$Ld7#x|2`)3@B3eo|BW*L zpC$c-`GUSx(x*s!ahqoxo-X@$Q0fQX6Nr1>Ec^GP(mwLu5YXq#{9AU5^3~poMn#vn zUFpv@N#C9j`FZag%DIy1_~Q9&llkwGeydu;|5Zunf( z9{9%(P?WI6XEKaJZik3RX0EN7a;hbfuAQR;`sB~IWySGcyH^UF+* zWHOH*2SI*)og7!&r5~;K8q7E3UncY4B<=6{)uNzPlKxjuzjwlp(DVN4?l@=Uy-N5t za+;w3>^}sZ_hNy50_^oP@L|hM>Ph)FtIN=yYh}H^knta7XWy^%gNzTqMHFNG1M-ty zvpja~!Ba(hUMBU-b29&zIR9&`J3ReztE~4+|4+#8;!DL1cQIYw>_{Gv`Cn)f_J#LY z;QG_D{Dem?#$^6yq@Szy5}YFWdD^dqUEn<+C})PcG=+0iB+=$@9FUGXLxM z3I6k*5#*0a`TF`dL^-@?5cFTka^B(T_ut8KUYIHP&wGoI|3yjv!ATAHg?+rQ<-~fu z99IwCF7orTdIgq%#lFtDMR`DxF2)pbN|MW{~D&(T0eiAD4)*^Kuw>P z^tLw&I-mIf`WGer<+}x4;hEbFyRWUaJJ~VV zH;_rT4sEt@d>oE;!@-zy-gfT7bNw?Vae!btNe6iiCvmFM0FJ+<7q}!lhI)F2af{>5}+?_vs|*)sjh^ z)=NjACUGQItHmz}PU7V-c)3Mu2iVb_vM47V>q`e(690R8l0A6iV_&;Pl_b@%rWwwt zepx9xSQCe2fsY&0cz-OtxEHU%=v|)_$7p5doO{lKh1RCNfek1WFL1zLoCC?t>ELez z9e7m?f1~&C4y5tsjigP(No05*2i}m}(YGGA;-JtZzhr|>$fe(z)O@>XAS9_KWa;Zq z_I6>YfVb%+=bAStFZT8&(c4LM4GJ@5@+)C}kP>tzUBc!RhHHPJM)>CPEkoCk^B~SL zkgIj$W)p8Ry={^=l*ykp<~+;iOYY^#a!&p%{ABLi{h!O6$IuFAG0Xj1p|j{#NY3SF zh9Q%y9i}|ahWO?2Yl&{AtD}h_juM=iOf7NcF|-7EI(u4;<7Gp)950l~FkXy#>~@*6 z=w|t65&Usob3T3SMLo1xc*yF{&6mCUVW>Z04nDgjXLDnz@^O)p({_>MIn{HnIT&jV7xuD$e3L{e^H}rOMC-rv$8Ht<=eC=IsK@+8&)m_t`i_neRn~v4lB9z(v|fq8kZoK;|ia~3lh!-O*SNCX^Ew)t>lHv zS1qnzo?NwTS#v{65{I%bZ%6_R0lwwx1OTTtV4}GpL^XJT;bFM{)kE2f1jh+Vdio34jgiRdcJ>Ve*V|=Em`yL>scU1x~C}c1(o7iF>ZR-+qr2>Q}1kRHk-%u@Y2EXP>((#1NF`EQ359G>Td~$!Q#PJl#2S7Fa9StVp&bRyWiy zZH9=lQeg!J*D3881)b;#k3{f*Anz~TVK>2p@6d(PS#%9JrvoVmpViaRZ()#v!EXM+ zQHIk;+G_w#!C+svW8Bb4s9)ZA;mQ>aD_eL>cr}KPJ|cahlcQWO98EEU@UGq|I=zoUzad(H295 z-=asn0qfjP49;fyl6ZjwP9)deLxO-xdisUGX(bz1p;El8K1nYf5Vl60BCc;zx}meR zCyf{Jz(y`!vus(z>gLAxHsoZ|G9-jP*N5ev@WTL#i~L|vXQ`xkVFU*6X0+KOPF##< zJW}72wd6Nu>I_0=$bG_frb@}SS{hcbXk1y}(xBvnj4tJ{`lS_2ZBBdY6>$eQt3_2V zSdNbB?Cc)Obh&e~`lfdisfSg(r8g1uLxo$+za+@iRqmU)8lMqC2;k!S)fOz)JbUQ4 zol|O0CYAEobFJocP)Ku2{puF+E)QSr4OSX%b_`MVaClcvGPN0Rx5&`jh0qYT!pUS? z2JtACe8mnis0WApQylBDIss6IpoI99Hw*-*%>E7QH3P*R-8c)s+e6EwKajG3-{e#1 z=DP6<9%R{?l}lP0SFLnBkt+n@d{%!IqRY-5kexW=-=l4H?p)!>3}^5%6OVFGgYj?h zK4JHWNWObxa%USARLZ> zX&i6aieg2>3M=EMRXh2`C+>QaNq|3z!`0BBj&B7lz*|z`1vv3QO@?(*a$VYZD`lnf?^K)Cb`5-8*FodIXqd|77iG5?Sy)D z>mKYyj=^6m(Z4;pa0_Mk+udaXJh##9hninWsFAJj^pNS}h7)Q&7ok$mp1JFG$A`~5 zt1u!dLgP4kL@0lE1=ZjNzk4faP_Iw(&~TW##?33#7}2*;WlUK7Cvkf62tJkDS*RMz zEx1B)9bRm8l_%%?2$yIJzf?7l@a{%ev`m^NN2giKT|}DW`&DE5zT?lEG)+qU6%_qO z?6v$4tHvr1U2(~zY5aMbS8@F{a4e}z?f+UeknnnE$8+BV5*hnRc+G3wfNlmK`A_kU zw%$1e#j~S|5pCqeR|_(hTzJJnzG0(4k0VR*^QtGlhH}QHOIEz(Jk}|a2A0P5vz= z59j{}usnB#SA6X;$M4ZNNawfOuk&w+vfRJoa3|0H?O%3&7Wfpe`#j>u?w@TS2`4^* zF88mv-tkVvryGNzLufe{`-2Q^>G-u?V*DcFM{Y*-Tgo_}fphwwFZ9Ce{;guxC5dA> zK=N$`p8Wa}9UoUk*B7GM(Y2G~PxIyRpik$b_AD6JFsk2l|KjzjV~;gsI({GVv!`cv8)f&KnKy6Vym{9g z-|W>V4f;j9tSra;wR28zn5x`8C|T;$ar&I)lQchqP9J9neD34?%;|tMOM>{vzo33H z-oc8$6#=k!8R7Rh6L3uFWT~xMXz72)^_9!7xkRSL9%I6Cws8aLoI04CL zJ<_`VG*!O-v{K1;zctc%J4!Y_0`freSTE<73Lxi~s-F2?PsI2$-==@;8~+W~{Ttja zh!oR7emMi=)B7eY|BBx$AHnB&Jyd)1dYmNr=6eYlhd=Xe>Ya{yq_e4ic^dEx-CjDr ze7yRC*ofa z|GMveLzkmBM!FofWYezyyl2y{$V&V7G^(cpxD14)%0Dg*d>AdHfhzm^AeCOOt;_8a$)Z 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

QiCs3^@`k2}p|zXW>1(&2$I2 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 literal 371121 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 Ma+eS~zveaj2Qo}E-~a#s diff --git a/LICENSE b/LICENSE index 9cecc1d4..bc08fe2e 100644 --- a/LICENSE +++ b/LICENSE @@ -617,58 +617,3 @@ reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {one line to give the program's name and a brief idea of what it does.} - Copyright (C) {year} {name of author} - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - {project} Copyright (C) {year} {fullname} - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/Makefile b/Makefile index 83b90e7e..adb946d5 100644 --- a/Makefile +++ b/Makefile @@ -44,11 +44,11 @@ cuda: FIRESTARTER_CUDA all: linux cuda -FIRESTARTER: generic.o x86.o main.o work.o x86.o watchdog.o help.o sse2_functions.o avx_functions.o fma_functions.o fma4_functions.o - ${LINUX_CC} -o FIRESTARTER generic.o main.o work.o x86.o watchdog.o help.o sse2_functions.o avx_functions.o fma_functions.o fma4_functions.o ${LINUX_L_FLAGS} +FIRESTARTER: generic.o x86.o main.o work.o x86.o watchdog.o help.o sse2_functions.o avx_functions.o fma_functions.o fma4_functions.o avx512_functions.o + ${LINUX_CC} -o FIRESTARTER generic.o main.o work.o x86.o watchdog.o help.o sse2_functions.o avx_functions.o fma_functions.o fma4_functions.o avx512_functions.o ${LINUX_L_FLAGS} -FIRESTARTER_CUDA: generic.o x86.o work.o x86.o watchdog.o sse2_functions.o avx_functions.o fma_functions.o fma4_functions.o gpu.o main_cuda.o help_cuda.o - ${LINUX_CC} -o FIRESTARTER_CUDA generic.o main_cuda.o work.o x86.o watchdog.o help_cuda.o sse2_functions.o avx_functions.o fma_functions.o fma4_functions.o gpu.o ${LINUX_CUDA_L_FLAGS} +FIRESTARTER_CUDA: generic.o x86.o work.o x86.o watchdog.o sse2_functions.o avx_functions.o fma_functions.o fma4_functions.o avx512_functions.o gpu.o main_cuda.o help_cuda.o + ${LINUX_CC} -o FIRESTARTER_CUDA generic.o main_cuda.o work.o x86.o watchdog.o help_cuda.o sse2_functions.o avx_functions.o fma_functions.o fma4_functions.o avx512_functions.o gpu.o ${LINUX_CUDA_L_FLAGS} generic.o: generic.c cpu.h ${LINUX_CC} ${OPT} ${LINUX_C_FLAGS} -c generic.c @@ -77,6 +77,9 @@ main_cuda.o: main.c work.h cpu.h help_cuda.o: help.c help.h ${LINUX_CC} ${OPT} ${LINUX_C_FLAGS} -o help_cuda.o -c help.c -DCUDA +avx512_functions.o: avx512_functions.c + ${LINUX_CC} ${OPT} ${LINUX_C_FLAGS} -mavx512f -c avx512_functions.c + fma4_functions.o: fma4_functions.c ${LINUX_CC} ${OPT} ${LINUX_C_FLAGS} -mfma4 -mavx -c fma4_functions.c diff --git a/README b/README index 9b737581..7168d62d 100644 --- a/README +++ b/README @@ -30,6 +30,7 @@ Supported CPU microarchitectures - Intel Ivy Bridge - Intel Haswell - Intel Skylake +- Intel Knights Landing - AMD Bulldozer (experimental) Since version 1.1 it is also possible to create alternating and repetitive @@ -54,8 +55,10 @@ Options: -c | --copyright display copyright information -w | --warranty display warranty information -q | --quiet disable output to stdout +-r | --report display additional information (overridden by -q) -a | --avail list available functions --i ID | --function=ID specify ID of the load-function to be used +-i ID | --function=ID specify integer ID of the load-function to be + used (as listed by --avail) -t TIMEOUT | --timeout=TIMEOUT set timeout (seconds) after which FIRESTARTER terminates itself, default: no timeout -l LOAD | --load=LOAD set the percentage of high load to LOAD (%), @@ -67,9 +70,12 @@ Options: load and an idle phase, the percentage of high load is defined by -l -n COUNT | --threads=COUNT specify the number of threads --b CPULIST | --bind=CPULIST select certain CPUs (overrides -n) + cannot be combined with -b | --bind, which + implicitly specifies the number of threads +-b CPULIST | --bind=CPULIST select certain CPUs CPULIST format: "x,y,z", "x-y", "x-y/step", and any combination of the above + cannot be combined with -n | --threads CUDA Options: -g | --gpus number of gpus to use (default: all) diff --git a/avx512_functions.c b/avx512_functions.c new file mode 100644 index 00000000..fe503168 --- /dev/null +++ b/avx512_functions.c @@ -0,0 +1,530 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2016 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#include "work.h" + + + + + int init_knl_xeonphi_avx512_4t(threaddata_t* threaddata) __attribute__((noinline)); +int init_knl_xeonphi_avx512_4t(threaddata_t* threaddata) +{ + unsigned long long addrMem = threaddata->addrMem; + int i; + for (i=0;i<836608;i++) *((double*)(addrMem+8*i)) = 0.25 + (double)(i%9267) * 0.24738995982e-4; + + // lines with register operations + threaddata->flops+=10*32; // 2 512 bit FMA operations + + // lines with L1 operations + threaddata->flops+=40*32; // 2 512 bit FMA operations + + // lines with L2 operations + threaddata->flops+=8*16; // 1 512 bit FMA operation + + // lines with RAM operations + threaddata->flops+=3*16; // 1 512 bit FMA operation + threaddata->bytes=3*64; // 1 memory access + + threaddata->flops*=6; + threaddata->bytes*=6; + + return EXIT_SUCCESS; +} + +/** + * assembler implementation of processor and memory stress test + * uses AVX512F instruction set + * optimized for Intel Xeon Phi (Knights Landing) + * @input - addrMem: pointer to buffer + * @return EXIT_SUCCESS + */ +int asm_work_knl_xeonphi_avx512_4t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_knl_xeonphi_avx512_4t(threaddata_t* threaddata) +{ + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; + /* input: + * - addrMem -> rax + * register usage: + * - rax: stores original pointer to buffer, used to periodically reset other pointers + * - rbx: pointer to L1 buffer + * - rcx: pointer to L2 buffer + * - r8: pointer to L3 buffer + * - r9: pointer to RAM buffer + * - r10: counter for L2-pointer reset + * - r11: counter for L3-pointer reset + * - r12: counter for RAM-pointer reset + * - r13: register for temporary results + * - r14: stores cacheline width as increment for buffer addresses + * - r15: stores address of shared variable that controls load level + * - mm0: stores iteration counter + * - rdx, rsi, rdi: registers for shift operations + * - xmm*,zmm*: data registers for SIMD instructions + */ + __asm__ __volatile__( + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r15;" // store address of shared variable that controls load level + "movq %%rcx, %%mm0;" // store iteration counter + "mov $64, %%r14;" // increment after each cache/memory access + //Initialize registers for shift operations + "mov $0xAAAAAAAA, %%edi;" + "mov $0xAAAAAAAA, %%esi;" + "mov $0xAAAAAAAA, %%edx;" + //Initialize AVX-Registers for FMA Operations + "vmovapd (%%rax), %%zmm0;" + "vmovapd (%%rax), %%zmm1;" + "vmovapd 384(%%rax), %%zmm2;" + "vmovapd 448(%%rax), %%zmm3;" + "vmovapd 512(%%rax), %%zmm4;" + "vmovapd 576(%%rax), %%zmm5;" + "vmovapd 640(%%rax), %%zmm6;" + "vmovapd 704(%%rax), %%zmm7;" + "vmovapd 768(%%rax), %%zmm8;" + "vmovapd 832(%%rax), %%zmm9;" + "vmovapd 896(%%rax), %%zmm10;" + "vmovapd 960(%%rax), %%zmm11;" + "vmovapd 1024(%%rax), %%zmm12;" + "vmovapd 1088(%%rax), %%zmm13;" + "vmovapd 1152(%%rax), %%zmm14;" + "vmovapd 1216(%%rax), %%zmm15;" + "vmovapd 1280(%%rax), %%zmm16;" + "vmovapd 1344(%%rax), %%zmm17;" + "vmovapd 1408(%%rax), %%zmm18;" + "vmovapd 1472(%%rax), %%zmm19;" + "vmovapd 1536(%%rax), %%zmm20;" + "vmovapd 1600(%%rax), %%zmm21;" + "vmovapd 1664(%%rax), %%zmm22;" + "vmovapd 1728(%%rax), %%zmm23;" + "vmovapd 1792(%%rax), %%zmm24;" + "vmovapd 1856(%%rax), %%zmm25;" + "vmovapd 1920(%%rax), %%zmm26;" + "vmovapd 1984(%%rax), %%zmm27;" + "vmovapd 2048(%%rax), %%zmm28;" + "vmovapd 2112(%%rax), %%zmm29;" + "vmovapd 2176(%%rax), %%zmm30;" + "mov %%rax, %%rbx;" // address for L1-buffer + "mov %%rax, %%rcx;" + "add $8192, %%rcx;" // address for L2-buffer + "mov %%rax, %%r8;" + "add $131072, %%r8;" // address for L3-buffer + "mov %%rax, %%r9;" + "add $0, %%r9;" // address for RAM-buffer + "movabs $34, %%r10;" // reset-counter for L2-buffer with 48 cache line accesses per loop (102 KB) + "movabs $0, %%r11;" // reset-counter for L3-buffer with 0 cache line accesses per loop (0 KB) + "movabs $5688, %%r12;" // reset-counter for RAM-buffer with 18 cache line accesses per loop (6399 KB) + + ".align 64;" /* alignment in bytes */ + "_work_loop_knl_xeonphi_avx512_4t:" + /***************************************************************************************************************************************************** + decode 0 decode 1 decode 2 decode 3 */ + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm3; prefetcht2 (%%r9); shl $1, %%edi; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd %%zmm6, %%zmm1, %%zmm26; shl $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm5; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm7, %%zmm0, %%zmm6; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm6; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm9, %%zmm0, %%zmm8; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm8; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm9, 64(%%rcx); vfmadd231pd %%zmm10, %%zmm0, %%zmm9; shl $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm11, %%zmm0, %%zmm10; vfmadd231pd %%zmm12, %%zmm1, %%zmm27; shl $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm11; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm13, %%zmm0, %%zmm12; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm12; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm14, %%zmm0, %%zmm13; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm13; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm14; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm15, 64(%%rcx); vfmadd231pd %%zmm16, %%zmm0, %%zmm15; shl $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm17, %%zmm0, %%zmm16; vfmadd231pd %%zmm18, %%zmm1, %%zmm28; shl $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm18, %%zmm0, %%zmm17; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm17; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm18; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm20, %%zmm0, %%zmm19; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm19; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm20, 64(%%rcx); vfmadd231pd %%zmm21, %%zmm0, %%zmm20; shr $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm22, %%zmm0, %%zmm21; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm21; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd %%zmm24, %%zmm1, %%zmm29; shl $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm24, %%zmm0, %%zmm23; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm23; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm24; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm2, %%zmm0, %%zmm25; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm25; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm2; prefetcht2 (%%r9); shr $1, %%edx; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm3; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd %%zmm6, %%zmm1, %%zmm30; shl $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm5; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm7, %%zmm0, %%zmm6; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm6; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm8, 64(%%rcx); vfmadd231pd %%zmm9, %%zmm0, %%zmm8; shr $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm9; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm11, %%zmm0, %%zmm10; vfmadd231pd %%zmm12, %%zmm1, %%zmm26; shl $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm11; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm13, %%zmm0, %%zmm12; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm12; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm13, 64(%%rcx); vfmadd231pd %%zmm14, %%zmm0, %%zmm13; shr $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm14; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm16, %%zmm0, %%zmm15; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm15; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm17, %%zmm0, %%zmm16; vfmadd231pd %%zmm18, %%zmm1, %%zmm27; shl $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm18, %%zmm0, %%zmm17; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm17; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm18; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm19, 64(%%rcx); vfmadd231pd %%zmm20, %%zmm0, %%zmm19; shr $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm20; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm22, %%zmm0, %%zmm21; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm21; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd %%zmm24, %%zmm1, %%zmm28; shl $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm24, %%zmm0, %%zmm23; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm23; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm24; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm25; prefetcht2 (%%r9); shr $1, %%esi; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm3, %%zmm0, %%zmm2; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm3; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd %%zmm6, %%zmm1, %%zmm29; shl $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm5; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm6, 64(%%rcx); vfmadd231pd %%zmm7, %%zmm0, %%zmm6; shr $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm9, %%zmm0, %%zmm8; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm8; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm9; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm11, %%zmm0, %%zmm10; vfmadd231pd %%zmm12, %%zmm1, %%zmm30; shl $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm11; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm12, 64(%%rcx); vfmadd231pd %%zmm13, %%zmm0, %%zmm12; shr $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm14, %%zmm0, %%zmm13; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm13; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm14; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm16, %%zmm0, %%zmm15; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm15; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm16; prefetcht2 (%%r9); shl $1, %%esi; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm18, %%zmm0, %%zmm17; vfmadd231pd %%zmm19, %%zmm1, %%zmm26; shl $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm18; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm20, %%zmm0, %%zmm19; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm19; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm20; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm22, %%zmm0, %%zmm21; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm21; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm22, 64(%%rcx); vfmadd231pd %%zmm23, %%zmm0, %%zmm22; shl $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm24, %%zmm0, %%zmm23; vfmadd231pd %%zmm25, %%zmm1, %%zmm27; shl $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm24; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm2, %%zmm0, %%zmm25; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm25; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm3, %%zmm0, %%zmm2; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm3; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm4, 64(%%rcx); vfmadd231pd %%zmm5, %%zmm0, %%zmm4; shl $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd %%zmm7, %%zmm1, %%zmm28; shl $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm7, %%zmm0, %%zmm6; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm6; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm9, %%zmm0, %%zmm8; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm8; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm9, 64(%%rcx); vfmadd231pd %%zmm10, %%zmm0, %%zmm9; shl $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm11, %%zmm0, %%zmm10; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm10; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd %%zmm13, %%zmm1, %%zmm29; shl $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm13, %%zmm0, %%zmm12; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm12; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm14, %%zmm0, %%zmm13; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm13; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm14; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm15; prefetcht2 (%%r9); shl $1, %%edi; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm17, %%zmm0, %%zmm16; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm16; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm18, %%zmm0, %%zmm17; vfmadd231pd %%zmm19, %%zmm1, %%zmm30; shl $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm18; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm20, %%zmm0, %%zmm19; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm19; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm20; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm21, 64(%%rcx); vfmadd231pd %%zmm22, %%zmm0, %%zmm21; shl $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm22; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm24, %%zmm0, %%zmm23; vfmadd231pd %%zmm25, %%zmm1, %%zmm26; shl $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm24; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm2, %%zmm0, %%zmm25; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm25; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm2, 64(%%rcx); vfmadd231pd %%zmm3, %%zmm0, %%zmm2; shr $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm3; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm4; shl $1, %%esi; mov %%rax, %%rbx;" // L1 load + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd %%zmm7, %%zmm1, %%zmm27; shl $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm7, %%zmm0, %%zmm6; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm6; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm8, 64(%%rcx); vfmadd231pd %%zmm9, %%zmm0, %%zmm8; shr $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm9; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm11, %%zmm0, %%zmm10; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm10; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd %%zmm13, %%zmm1, %%zmm28; shl $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm13, %%zmm0, %%zmm12; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm12; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm14, %%zmm0, %%zmm13; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm13; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm14; prefetcht2 (%%r9); shr $1, %%edx; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm16, %%zmm0, %%zmm15; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm15; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm17, %%zmm0, %%zmm16; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm16; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm18, %%zmm0, %%zmm17; vfmadd231pd %%zmm19, %%zmm1, %%zmm29; shl $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm18; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm19, 64(%%rcx); vfmadd231pd %%zmm20, %%zmm0, %%zmm19; shr $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm20; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm22, %%zmm0, %%zmm21; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm21; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm22; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm24, %%zmm0, %%zmm23; vfmadd231pd %%zmm25, %%zmm1, %%zmm30; shl $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm24; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm25, 64(%%rcx); vfmadd231pd %%zmm2, %%zmm0, %%zmm25; shr $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm3, %%zmm0, %%zmm2; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm3; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm4; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm5; prefetcht2 (%%r9); shl $1, %%edx; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm7, %%zmm0, %%zmm6; vfmadd231pd %%zmm8, %%zmm1, %%zmm26; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm9, %%zmm0, %%zmm8; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm8; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm9; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm11, %%zmm0, %%zmm10; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm10; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm11, 64(%%rcx); vfmadd231pd %%zmm12, %%zmm0, %%zmm11; shl $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm13, %%zmm0, %%zmm12; vfmadd231pd %%zmm14, %%zmm1, %%zmm27; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm14, %%zmm0, %%zmm13; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm13; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm14; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm16, %%zmm0, %%zmm15; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm15; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm17, %%zmm0, %%zmm16; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm16; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm17, 64(%%rcx); vfmadd231pd %%zmm18, %%zmm0, %%zmm17; shl $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd %%zmm20, %%zmm1, %%zmm28; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm20, %%zmm0, %%zmm19; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm19; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm20; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm22, %%zmm0, %%zmm21; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm21; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm22, 64(%%rcx); vfmadd231pd %%zmm23, %%zmm0, %%zmm22; shl $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm24, %%zmm0, %%zmm23; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm23; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd %%zmm2, %%zmm1, %%zmm29; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm2, %%zmm0, %%zmm25; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm25; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm3, %%zmm0, %%zmm2; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm3; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm4; prefetcht2 (%%r9); shl $1, %%esi; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm5; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm7, %%zmm0, %%zmm6; vfmadd231pd %%zmm8, %%zmm1, %%zmm30; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm9, %%zmm0, %%zmm8; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm8; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm9; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm10, 64(%%rcx); vfmadd231pd %%zmm11, %%zmm0, %%zmm10; shl $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm11; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm13, %%zmm0, %%zmm12; vfmadd231pd %%zmm14, %%zmm1, %%zmm26; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm14, %%zmm0, %%zmm13; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm13; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm14; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm15, 64(%%rcx); vfmadd231pd %%zmm16, %%zmm0, %%zmm15; shl $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm17, %%zmm0, %%zmm16; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm16; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm18, %%zmm0, %%zmm17; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm17; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd %%zmm20, %%zmm1, %%zmm27; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm20, %%zmm0, %%zmm19; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm19; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm20; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm21, 64(%%rcx); vfmadd231pd %%zmm22, %%zmm0, %%zmm21; shl $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm22; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm24, %%zmm0, %%zmm23; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm23; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd %%zmm2, %%zmm1, %%zmm28; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm2, %%zmm0, %%zmm25; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm25; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm3, %%zmm0, %%zmm2; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm3; prefetcht2 (%%r9); shl $1, %%edi; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm4; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm5; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm7, %%zmm0, %%zmm6; vfmadd231pd %%zmm8, %%zmm1, %%zmm29; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm8, 64(%%rcx); vfmadd231pd %%zmm9, %%zmm0, %%zmm8; shr $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm9; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm11, %%zmm0, %%zmm10; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm10; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm11; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm13, %%zmm0, %%zmm12; vfmadd231pd %%zmm14, %%zmm1, %%zmm30; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm14, %%zmm0, %%zmm13; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm13; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm14, 64(%%rcx); vfmadd231pd %%zmm15, %%zmm0, %%zmm14; shr $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm16, %%zmm0, %%zmm15; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm15; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm17, %%zmm0, %%zmm16; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm16; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm18, %%zmm0, %%zmm17; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm17; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm18; prefetcht2 (%%r9); shr $1, %%edi; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm20, %%zmm0, %%zmm19; vfmadd231pd %%zmm21, %%zmm1, %%zmm26; shr $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm20; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm22, %%zmm0, %%zmm21; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm21; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm22; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm24, %%zmm0, %%zmm23; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm23; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm24, 64(%%rcx); vfmadd231pd %%zmm25, %%zmm0, %%zmm24; shr $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm2, %%zmm0, %%zmm25; vfmadd231pd %%zmm3, %%zmm1, %%zmm27; shr $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm3, %%zmm0, %%zmm2; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm3; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm4; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm5; shl $1, %%edx; mov %%rax, %%rbx;" // L1 load + "vmovapd %%zmm6, 64(%%rcx); vfmadd231pd %%zmm7, %%zmm0, %%zmm6; shr $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd %%zmm9, %%zmm1, %%zmm28; shr $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm9, %%zmm0, %%zmm8; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm8; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm9; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm11, %%zmm0, %%zmm10; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm10; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm11, 64(%%rcx); vfmadd231pd %%zmm12, %%zmm0, %%zmm11; shl $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm13, %%zmm0, %%zmm12; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm12; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm14, %%zmm0, %%zmm13; vfmadd231pd %%zmm15, %%zmm1, %%zmm29; shr $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm14; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm16, %%zmm0, %%zmm15; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm15; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm17, %%zmm0, %%zmm16; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm16; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm17; prefetcht2 (%%r9); shl $1, %%edx; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm18; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm20, %%zmm0, %%zmm19; vfmadd231pd %%zmm21, %%zmm1, %%zmm30; shr $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm20; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm22, %%zmm0, %%zmm21; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm21; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm22; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm23, 64(%%rcx); vfmadd231pd %%zmm24, %%zmm0, %%zmm23; shl $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm24; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm2, %%zmm0, %%zmm25; vfmadd231pd %%zmm3, %%zmm1, %%zmm26; shr $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm3, %%zmm0, %%zmm2; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm3; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm4, 64(%%rcx); vfmadd231pd %%zmm5, %%zmm0, %%zmm4; shl $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm5; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm7, %%zmm0, %%zmm6; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm6; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd %%zmm9, %%zmm1, %%zmm27; shr $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm9, %%zmm0, %%zmm8; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm8; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm9; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm10, 64(%%rcx); vfmadd231pd %%zmm11, %%zmm0, %%zmm10; shl $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm11; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm13, %%zmm0, %%zmm12; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm12; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm14, %%zmm0, %%zmm13; vfmadd231pd %%zmm15, %%zmm1, %%zmm28; shr $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm14; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm16, %%zmm0, %%zmm15; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm15; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm16; prefetcht2 (%%r9); shl $1, %%esi; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm18, %%zmm0, %%zmm17; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm17; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm18; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm20, %%zmm0, %%zmm19; vfmadd231pd %%zmm21, %%zmm1, %%zmm29; shr $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm20; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm21, 64(%%rcx); vfmadd231pd %%zmm22, %%zmm0, %%zmm21; shl $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm22; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm24, %%zmm0, %%zmm23; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm23; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm24; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm2, %%zmm0, %%zmm25; vfmadd231pd %%zmm3, %%zmm1, %%zmm30; shr $1, %%esi; xor %%rdi, %%r13; " // REG ops only + "vfmadd231pd %%zmm3, %%zmm0, %%zmm2; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm3, 64(%%rcx); vfmadd231pd %%zmm4, %%zmm0, %%zmm3; shl $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm4; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm5; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm7, %%zmm0, %%zmm6; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm6; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm7; prefetcht2 (%%r9); shr $1, %%esi; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm9, %%zmm0, %%zmm8; vfmadd231pd %%zmm10, %%zmm1, %%zmm26; shr $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm9; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm11, %%zmm0, %%zmm10; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm10; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm11; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm13, %%zmm0, %%zmm12; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm12; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm13, 64(%%rcx); vfmadd231pd %%zmm14, %%zmm0, %%zmm13; shr $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd %%zmm16, %%zmm1, %%zmm27; shr $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm16, %%zmm0, %%zmm15; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm15; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm17, %%zmm0, %%zmm16; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm16; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm18, %%zmm0, %%zmm17; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm17; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm18; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm19, 64(%%rcx); vfmadd231pd %%zmm20, %%zmm0, %%zmm19; shr $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd %%zmm22, %%zmm1, %%zmm28; shr $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm22, %%zmm0, %%zmm21; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm21; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm22; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm24, %%zmm0, %%zmm23; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm23; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm24, 64(%%rcx); vfmadd231pd %%zmm25, %%zmm0, %%zmm24; shr $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm2, %%zmm0, %%zmm25; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm25; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm3, %%zmm0, %%zmm2; vfmadd231pd %%zmm4, %%zmm1, %%zmm29; shr $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm3; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm4; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm5; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm6; prefetcht2 (%%r9); shr $1, %%edi; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm9, %%zmm0, %%zmm8; vfmadd231pd %%zmm10, %%zmm1, %%zmm30; shr $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm9; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm11, %%zmm0, %%zmm10; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm10; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm11; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm12, 64(%%rcx); vfmadd231pd %%zmm13, %%zmm0, %%zmm12; shr $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm14, %%zmm0, %%zmm13; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm13; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd %%zmm16, %%zmm1, %%zmm26; shr $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm16, %%zmm0, %%zmm15; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm15; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm17, %%zmm0, %%zmm16; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm16; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm17, 64(%%rcx); vfmadd231pd %%zmm18, %%zmm0, %%zmm17; shl $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm18; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm20, %%zmm0, %%zmm19; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm19; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd %%zmm22, %%zmm1, %%zmm27; shr $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm22, %%zmm0, %%zmm21; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm21; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm22; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm23, 64(%%rcx); vfmadd231pd %%zmm24, %%zmm0, %%zmm23; shl $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm24; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm2, %%zmm0, %%zmm25; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm25; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm3, %%zmm0, %%zmm2; vfmadd231pd %%zmm4, %%zmm1, %%zmm28; shr $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm3; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm4; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm5; prefetcht2 (%%r9); shl $1, %%edx; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm7, %%zmm0, %%zmm6; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm6; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; mov %%rax, %%rbx;" // L1 load + "vfmadd231pd %%zmm9, %%zmm0, %%zmm8; vfmadd231pd %%zmm10, %%zmm1, %%zmm29; shr $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm9; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm10, 64(%%rcx); vfmadd231pd %%zmm11, %%zmm0, %%zmm10; shl $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm11; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm13, %%zmm0, %%zmm12; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm12; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm14, %%zmm0, %%zmm13; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm13; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd %%zmm16, %%zmm1, %%zmm30; shr $1, %%edx; xor %%rsi, %%r13; " // REG ops only + "vfmadd231pd %%zmm16, %%zmm0, %%zmm15; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm15; shl $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm16, 64(%%rcx); vfmadd231pd %%zmm17, %%zmm0, %%zmm16; shl $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm18, %%zmm0, %%zmm17; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm17; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm18; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm20, %%zmm0, %%zmm19; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm19; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm20; prefetcht2 (%%r9); shr $1, %%edx; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm22, %%zmm0, %%zmm21; vfmadd231pd %%zmm23, %%zmm1, %%zmm26; shl $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm22; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm24, %%zmm0, %%zmm23; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm23; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm24; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm2, %%zmm0, %%zmm25; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm25; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm2, 64(%%rcx); vfmadd231pd %%zmm3, %%zmm0, %%zmm2; shr $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd %%zmm5, %%zmm1, %%zmm27; shl $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm4; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm5; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm7, %%zmm0, %%zmm6; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm6; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm8, 64(%%rcx); vfmadd231pd %%zmm9, %%zmm0, %%zmm8; shr $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd %%zmm11, %%zmm1, %%zmm28; shl $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm11, %%zmm0, %%zmm10; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm10; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm11; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm13, %%zmm0, %%zmm12; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm12; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm13, 64(%%rcx); vfmadd231pd %%zmm14, %%zmm0, %%zmm13; shr $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm14; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm16, %%zmm0, %%zmm15; vfmadd231pd %%zmm17, %%zmm1, %%zmm29; shl $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm17, %%zmm0, %%zmm16; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm16; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm18, %%zmm0, %%zmm17; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm17; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm19, %%zmm0, %%zmm18; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm18; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm19; prefetcht2 (%%r9); shr $1, %%esi; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm20; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm22, %%zmm0, %%zmm21; vfmadd231pd %%zmm23, %%zmm1, %%zmm30; shl $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm22; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm24, %%zmm0, %%zmm23; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm23; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm24; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm25, 64(%%rcx); vfmadd231pd %%zmm2, %%zmm0, %%zmm25; shr $1, %%esi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm3, %%zmm0, %%zmm2; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd %%zmm5, %%zmm1, %%zmm26; shl $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm4; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm6, %%zmm0, %%zmm5; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm5; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm6, 64(%%rcx); vfmadd231pd %%zmm7, %%zmm0, %%zmm6; shr $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm9, %%zmm0, %%zmm8; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm8; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm10, %%zmm0, %%zmm9; vfmadd231pd %%zmm11, %%zmm1, %%zmm27; shl $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm11, %%zmm0, %%zmm10; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm10; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm12, %%zmm0, %%zmm11; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm11; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm12, 64(%%rcx); vfmadd231pd %%zmm13, %%zmm0, %%zmm12; shr $1, %%edi; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm14, %%zmm0, %%zmm13; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm13; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm15, %%zmm0, %%zmm14; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm14; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm16, %%zmm0, %%zmm15; vfmadd231pd %%zmm17, %%zmm1, %%zmm28; shl $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm17, %%zmm0, %%zmm16; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm16; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm18, %%zmm0, %%zmm17; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm17; shl $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd 64(%%rbx), %%zmm0, %%zmm18; prefetcht2 (%%r9); shr $1, %%edi; add %%r14, %%r9; " // RAM prefetch + "vfmadd231pd %%zmm20, %%zmm0, %%zmm19; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm19; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm21, %%zmm0, %%zmm20; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm20; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm22, %%zmm0, %%zmm21; vfmadd231pd %%zmm23, %%zmm1, %%zmm29; shl $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm23, %%zmm0, %%zmm22; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm22; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm23, 64(%%rcx); vfmadd231pd %%zmm24, %%zmm0, %%zmm23; shl $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm25, %%zmm0, %%zmm24; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm24; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm2, %%zmm0, %%zmm25; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm25; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm3, %%zmm0, %%zmm2; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm4, %%zmm0, %%zmm3; vfmadd231pd %%zmm5, %%zmm1, %%zmm30; shl $1, %%edi; xor %%rdx, %%r13; " // REG ops only + "vfmadd231pd %%zmm5, %%zmm0, %%zmm4; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm4; shl $1, %%esi; add %%r14, %%rbx; " // L1 load + "vmovapd %%zmm5, 64(%%rcx); vfmadd231pd %%zmm6, %%zmm0, %%zmm5; shl $1, %%edx; add %%r14, %%rcx; " // L2 store + "vfmadd231pd %%zmm7, %%zmm0, %%zmm6; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm6; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm8, %%zmm0, %%zmm7; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm7; shr $1, %%esi; add %%r14, %%rbx; " // L1 load + "vfmadd231pd %%zmm9, %%zmm0, %%zmm8; vfmadd231pd 64(%%rbx), %%zmm1, %%zmm8; shr $1, %%edx; add %%r14, %%rbx; " // L1 load + "movq %%mm0, %%r13;" // restore iteration counter + //reset RAM counter + "sub $1, %%r12;" + "jnz _work_no_ram_reset_knl_xeonphi_avx512_4t;" + "movabs $5688, %%r12;" + "mov %%rax, %%r9;" + "add $0, %%r9;" + "_work_no_ram_reset_knl_xeonphi_avx512_4t:" + "inc %%r13;" // increment iteration counter + //reset L2-Cache counter + "sub $1, %%r10;" + "jnz _work_no_L2_reset_knl_xeonphi_avx512_4t;" + "movabs $34, %%r10;" + "mov %%rax, %%rcx;" + "add $8192, %%rcx;" + "_work_no_L2_reset_knl_xeonphi_avx512_4t:" + "movq %%r13, %%mm0;" // store iteration counter + "mov %%rax, %%rbx;" + "testq $1, (%%r15);" + "jnz _work_loop_knl_xeonphi_avx512_4t;" + "movq %%mm0, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15", "%xmm16", "%xmm17", "%xmm18", "%xmm19", "%xmm20", "%xmm21", "%xmm22", "%xmm23", "%xmm24", "%xmm25", "%xmm26", "%xmm27", "%xmm28", "%xmm29", "%xmm30", "%xmm31" + ); + return EXIT_SUCCESS; +} diff --git a/avx_functions.c b/avx_functions.c index 5a4c6faa..0d1fd4b4 100644 --- a/avx_functions.c +++ b/avx_functions.c @@ -23,12 +23,33 @@ - int init_snb_corei_avx_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_snb_corei_avx_1t(unsigned long long addrMem) + + int init_snb_corei_avx_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_snb_corei_avx_1t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i=0;i<13340672;i++) *((double*)(addrMem+8*i)) = i* 1.654738925401e-15; + // lines with register operations + threaddata->flops+=45*4; // 1 256 bit operation + + // lines with L1 operations + threaddata->flops+=90*4; // 1 256 bit operation + + // lines with L2 operations + threaddata->flops+=10*4; // 1 256 bit operation + + // lines with L3 operations + threaddata->flops+=4*4; // 1 256 bit operation + + // lines with RAM operations + threaddata->flops+=2*4; // 1 256 bit operation + threaddata->bytes=2*64; // 1 memory access + + threaddata->flops*=10; + threaddata->bytes*=10; + return EXIT_SUCCESS; } @@ -39,11 +60,11 @@ int init_snb_corei_avx_1t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_snb_corei_avx_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_snb_corei_avx_1t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_snb_corei_avx_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_snb_corei_avx_1t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -58,11 +79,13 @@ int asm_work_snb_corei_avx_1t(unsigned long long addrMem, unsigned long long add * - r11: temp register for initialization of SIMD-registers * - r12: stores cacheline width as increment for buffer addresses * - r13: stores address of shared variable that controls load level + * - r14: stores iteration counter * - mm*,xmm*,ymm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r13;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r13;" // store address of shared variable that controls load level + "mov %%rcx, %%r14;" // store iteration counter "mov $64, %%r12;" // increment after each cache/memory access //Initialize AVX-Registers for Addition "vmovapd 0(%%rax), %%ymm0;" @@ -1654,26 +1677,48 @@ int asm_work_snb_corei_avx_1t(unsigned long long addrMem, unsigned long long add "mov %%rax, %%rdx;" "add $262144, %%rdx;" "_work_no_L3_reset_snb_corei_avx_1t:" + "inc %%r14;" // increment iteration counter "mov %%rax, %%rbx;" "mfence;" - "mov (%%r13), %%r11;" - "test $1, %%r11;" + "testq $1, (%%r13);" "jnz _work_loop_snb_corei_avx_1t;" - : - : "r"(addrMem), "r"(addrHigh) - : "%rax", "%rbx", "%rcx", "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%r14, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } - int init_snb_corei_avx_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_snb_corei_avx_2t(unsigned long long addrMem) + + int init_snb_corei_avx_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_snb_corei_avx_2t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i=0;i<6670336;i++) *((double*)(addrMem+8*i)) = i* 1.654738925401e-15; + // lines with register operations + threaddata->flops+=45*4; // 1 256 bit operation + + // lines with L1 operations + threaddata->flops+=90*4; // 1 256 bit operation + + // lines with L2 operations + threaddata->flops+=10*4; // 1 256 bit operation + + // lines with L3 operations + threaddata->flops+=4*4; // 1 256 bit operation + + // lines with RAM operations + threaddata->flops+=2*4; // 1 256 bit operation + threaddata->bytes=2*64; // 1 memory access + + threaddata->flops*=5; + threaddata->bytes*=5; + return EXIT_SUCCESS; } @@ -1684,11 +1729,11 @@ int init_snb_corei_avx_2t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_snb_corei_avx_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_snb_corei_avx_2t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_snb_corei_avx_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_snb_corei_avx_2t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -1703,11 +1748,13 @@ int asm_work_snb_corei_avx_2t(unsigned long long addrMem, unsigned long long add * - r11: temp register for initialization of SIMD-registers * - r12: stores cacheline width as increment for buffer addresses * - r13: stores address of shared variable that controls load level + * - r14: stores iteration counter * - mm*,xmm*,ymm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r13;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r13;" // store address of shared variable that controls load level + "mov %%rcx, %%r14;" // store iteration counter "mov $64, %%r12;" // increment after each cache/memory access //Initialize AVX-Registers for Addition "vmovapd 0(%%rax), %%ymm0;" @@ -2544,26 +2591,48 @@ int asm_work_snb_corei_avx_2t(unsigned long long addrMem, unsigned long long add "mov %%rax, %%rdx;" "add $131072, %%rdx;" "_work_no_L3_reset_snb_corei_avx_2t:" + "inc %%r14;" // increment iteration counter "mov %%rax, %%rbx;" "mfence;" - "mov (%%r13), %%r11;" - "test $1, %%r11;" + "testq $1, (%%r13);" "jnz _work_loop_snb_corei_avx_2t;" - : - : "r"(addrMem), "r"(addrHigh) - : "%rax", "%rbx", "%rcx", "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%r14, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } - int init_snb_xeonep_avx_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_snb_xeonep_avx_1t(unsigned long long addrMem) + + int init_snb_xeonep_avx_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_snb_xeonep_avx_1t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i=0;i<13471744;i++) *((double*)(addrMem+8*i)) = i* 1.654738925401e-15; + // lines with register operations + threaddata->flops+=30*4; // 1 256 bit operation + + // lines with L1 operations + threaddata->flops+=90*4; // 1 256 bit operation + + // lines with L2 operations + threaddata->flops+=10*4; // 1 256 bit operation + + // lines with L3 operations + threaddata->flops+=2*4; // 1 256 bit operation + + // lines with RAM operations + threaddata->flops+=3*4; // 1 256 bit operation + threaddata->bytes=3*64; // 1 memory access + + threaddata->flops*=11; + threaddata->bytes*=11; + return EXIT_SUCCESS; } @@ -2574,11 +2643,11 @@ int init_snb_xeonep_avx_1t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_snb_xeonep_avx_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_snb_xeonep_avx_1t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_snb_xeonep_avx_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_snb_xeonep_avx_1t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -2593,11 +2662,13 @@ int asm_work_snb_xeonep_avx_1t(unsigned long long addrMem, unsigned long long ad * - r11: temp register for initialization of SIMD-registers * - r12: stores cacheline width as increment for buffer addresses * - r13: stores address of shared variable that controls load level + * - r14: stores iteration counter * - mm*,xmm*,ymm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r13;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r13;" // store address of shared variable that controls load level + "mov %%rcx, %%r14;" // store iteration counter "mov $64, %%r12;" // increment after each cache/memory access //Initialize AVX-Registers for Addition "vmovapd 0(%%rax), %%ymm0;" @@ -4164,26 +4235,48 @@ int asm_work_snb_xeonep_avx_1t(unsigned long long addrMem, unsigned long long ad "mov %%rax, %%rdx;" "add $262144, %%rdx;" "_work_no_L3_reset_snb_xeonep_avx_1t:" + "inc %%r14;" // increment iteration counter "mov %%rax, %%rbx;" "mfence;" - "mov (%%r13), %%r11;" - "test $1, %%r11;" + "testq $1, (%%r13);" "jnz _work_loop_snb_xeonep_avx_1t;" - : - : "r"(addrMem), "r"(addrHigh) - : "%rax", "%rbx", "%rcx", "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%r14, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } - int init_snb_xeonep_avx_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_snb_xeonep_avx_2t(unsigned long long addrMem) + + int init_snb_xeonep_avx_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_snb_xeonep_avx_2t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i=0;i<6735872;i++) *((double*)(addrMem+8*i)) = i* 1.654738925401e-15; + // lines with register operations + threaddata->flops+=30*4; // 1 256 bit operation + + // lines with L1 operations + threaddata->flops+=90*4; // 1 256 bit operation + + // lines with L2 operations + threaddata->flops+=10*4; // 1 256 bit operation + + // lines with L3 operations + threaddata->flops+=2*4; // 1 256 bit operation + + // lines with RAM operations + threaddata->flops+=3*4; // 1 256 bit operation + threaddata->bytes=3*64; // 1 memory access + + threaddata->flops*=5; + threaddata->bytes*=5; + return EXIT_SUCCESS; } @@ -4194,11 +4287,11 @@ int init_snb_xeonep_avx_2t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_snb_xeonep_avx_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_snb_xeonep_avx_2t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_snb_xeonep_avx_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_snb_xeonep_avx_2t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -4213,11 +4306,13 @@ int asm_work_snb_xeonep_avx_2t(unsigned long long addrMem, unsigned long long ad * - r11: temp register for initialization of SIMD-registers * - r12: stores cacheline width as increment for buffer addresses * - r13: stores address of shared variable that controls load level + * - r14: stores iteration counter * - mm*,xmm*,ymm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r13;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r13;" // store address of shared variable that controls load level + "mov %%rcx, %%r14;" // store iteration counter "mov $64, %%r12;" // increment after each cache/memory access //Initialize AVX-Registers for Addition "vmovapd 0(%%rax), %%ymm0;" @@ -4974,14 +5069,15 @@ int asm_work_snb_xeonep_avx_2t(unsigned long long addrMem, unsigned long long ad "mov %%rax, %%rdx;" "add $131072, %%rdx;" "_work_no_L3_reset_snb_xeonep_avx_2t:" + "inc %%r14;" // increment iteration counter "mov %%rax, %%rbx;" "mfence;" - "mov (%%r13), %%r11;" - "test $1, %%r11;" + "testq $1, (%%r13);" "jnz _work_loop_snb_xeonep_avx_2t;" - : - : "r"(addrMem), "r"(addrHigh) - : "%rax", "%rbx", "%rcx", "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%r14, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } diff --git a/cpu.h b/cpu.h index a8045448..d38105fc 100644 --- a/cpu.h +++ b/cpu.h @@ -81,6 +81,7 @@ #define FMA4 0x00010000 #define FMA 0x00020000 #define AES 0x00040000 +#define AVX512 0x00080000 #define MAX_CACHELEVELS 3 diff --git a/firestarter_global.h b/firestarter_global.h index cec4ab86..85f7ad1d 100644 --- a/firestarter_global.h +++ b/firestarter_global.h @@ -25,9 +25,9 @@ /* current version */ #define VERSION_MAJOR 1 -#define VERSION_MINOR 4 +#define VERSION_MINOR 5 #define VERSION_INFO "" -#define BUILDDATE "2016-04-08" +#define BUILDDATE "2016-11-11" #define COPYRIGHT_YEAR 2016 #if (defined(linux) || defined(__linux__)) && defined (AFFINITY) @@ -84,7 +84,7 @@ typedef struct mydata { struct threaddata *threaddata; cpu_info_t *cpuinfo; - int *thread_comm; + int *thread_comm; volatile unsigned int ack; unsigned int num_threads; } mydata_t; @@ -96,7 +96,12 @@ typedef struct threaddata char* bufferMem; unsigned long long addrMem; unsigned long long addrHigh; - unsigned long long buffersizeMem; + unsigned long long buffersizeMem; + unsigned long long iterations; + unsigned long long flops; + unsigned long long bytes; + unsigned long long start_tsc; + unsigned long long stop_tsc; unsigned int alignment; unsigned int cpu_id; unsigned int thread_id; diff --git a/fma4_functions.c b/fma4_functions.c index 1bfaddc3..472ede26 100644 --- a/fma4_functions.c +++ b/fma4_functions.c @@ -23,12 +23,33 @@ - int init_bld_opteron_fma4_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_bld_opteron_fma4_1t(unsigned long long addrMem) + + int init_bld_opteron_fma4_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_bld_opteron_fma4_1t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i=0;i<13338624;i++) *((double*)(addrMem+8*i)) = 0.25 + (double)(i%9267) * 0.24738995982e-4; + // lines with register operations + threaddata->flops+=45*8; // 2 128 bit FMA operations + + // lines with L1 operations + threaddata->flops+=90*12; // 1 128 and 1 256 bit FMA operation + + // lines with L2 operations + threaddata->flops+=5*4; // 1 128 bit FMA operation + + // lines with L3 operations + threaddata->flops+=1*4; // 1 128 bit FMA operation + + // lines with RAM operations + threaddata->flops+=1*8; // 2 128 bit FMA operations + threaddata->bytes=1*64; // 1 memory access + + threaddata->flops*=10; + threaddata->bytes*=10; + return EXIT_SUCCESS; } @@ -39,10 +60,10 @@ int init_bld_opteron_fma4_1t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_bld_opteron_fma4_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_bld_opteron_fma4_1t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_bld_opteron_fma4_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_bld_opteron_fma4_1t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -57,12 +78,14 @@ int asm_work_bld_opteron_fma4_1t(unsigned long long addrMem, unsigned long long * - r13: register for temporary results * - r14: stores cacheline width as increment for buffer addresses * - r15: stores address of shared variable that controls load level + * - mm0: stores iteration counter * - rdx, rsi, rdi: registers for shift operations - * - mm*,xmm*,xmm*: data registers for SIMD instructions + * - xmm*,xmm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r15;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r15;" // store address of shared variable that controls load level + "movq %%rcx, %%mm0;" // store iteration counter "mov $64, %%r14;" // increment after each cache/memory access //Initialize registers for shift operations "mov $0xAAAAAAAA, %%edi;" @@ -1518,6 +1541,7 @@ int asm_work_bld_opteron_fma4_1t(unsigned long long addrMem, unsigned long long "vfmaddpd %%xmm8, %%xmm0, %%xmm7, %%xmm7; vfmaddpd %%xmm9, %%xmm1, %%xmm13, %%xmm13; shl $1, %%esi; xor %%rdi, %%r13; " // REG ops only "vfmaddpd %%xmm9, %%xmm0, %%xmm8, %%xmm8; vfmaddpd 32(%%rbx), %%ymm1, %%ymm8, %%ymm8; shl $1, %%edx; add %%r14, %%rbx; " // L1 load "vfmaddpd %%xmm10, %%xmm0, %%xmm9, %%xmm9; vfmaddpd 32(%%rbx), %%ymm1, %%ymm9, %%ymm9; shr $1, %%edi; add %%r14, %%rbx; " // L1 load + "movq %%mm0, %%r13;" // restore iteration counter //reset RAM counter "sub $1, %%r12;" "jnz _work_no_ram_reset_bld_opteron_fma4_1t;" @@ -1525,6 +1549,7 @@ int asm_work_bld_opteron_fma4_1t(unsigned long long addrMem, unsigned long long "mov %%rax, %%r9;" "add $786432, %%r9;" "_work_no_ram_reset_bld_opteron_fma4_1t:" + "inc %%r13;" // increment iteration counter //reset L2-Cache counter "sub $1, %%r10;" "jnz _work_no_L2_reset_bld_opteron_fma4_1t;" @@ -1532,6 +1557,7 @@ int asm_work_bld_opteron_fma4_1t(unsigned long long addrMem, unsigned long long "mov %%rax, %%rcx;" "add $16384, %%rcx;" "_work_no_L2_reset_bld_opteron_fma4_1t:" + "movq %%r13, %%mm0;" // store iteration counter //reset L3-Cache counter "sub $1, %%r11;" "jnz _work_no_L3_reset_bld_opteron_fma4_1t;" @@ -1540,12 +1566,12 @@ int asm_work_bld_opteron_fma4_1t(unsigned long long addrMem, unsigned long long "add $1048576, %%r8;" "_work_no_L3_reset_bld_opteron_fma4_1t:" "mov %%rax, %%rbx;" - "mov (%%r15), %%r13;" - "test $1, %%r13;" + "testq $1, (%%r15);" "jnz _work_loop_bld_opteron_fma4_1t;" - : - : "a"(addrMem), "b"(addrHigh) - : "%rcx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%mm0, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } diff --git a/fma_functions.c b/fma_functions.c index 8edf27df..39451246 100644 --- a/fma_functions.c +++ b/fma_functions.c @@ -23,12 +23,33 @@ - int init_skl_corei_fma_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_skl_corei_fma_1t(unsigned long long addrMem) + + int init_skl_corei_fma_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_skl_corei_fma_1t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i=0;i<13340672;i++) *((double*)(addrMem+8*i)) = 0.25 + (double)(i%9267) * 0.24738995982e-4; + // lines with register operations + threaddata->flops+=40*16; // 2 256 bit FMA operations + + // lines with L1 operations + threaddata->flops+=78*16; // 2 256 bit FMA operations + + // lines with L2 operations + threaddata->flops+=18*8; // 1 256 bit FMA operation + + // lines with L3 operations + threaddata->flops+=5*8; // 1 256 bit FMA operation + + // lines with RAM operations + threaddata->flops+=3*16; // 2 256 bit FMA operations + threaddata->bytes=3*64; // 1 memory access + + threaddata->flops*=10; + threaddata->bytes*=10; + return EXIT_SUCCESS; } @@ -39,10 +60,10 @@ int init_skl_corei_fma_1t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_skl_corei_fma_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_skl_corei_fma_1t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_skl_corei_fma_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_skl_corei_fma_1t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -57,12 +78,14 @@ int asm_work_skl_corei_fma_1t(unsigned long long addrMem, unsigned long long add * - r13: register for temporary results * - r14: stores cacheline width as increment for buffer addresses * - r15: stores address of shared variable that controls load level + * - mm0: stores iteration counter * - rdx, rsi, rdi: registers for shift operations - * - mm*,xmm*,ymm*: data registers for SIMD instructions + * - xmm*,ymm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r15;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r15;" // store address of shared variable that controls load level + "movq %%rcx, %%mm0;" // store iteration counter "mov $64, %%r14;" // increment after each cache/memory access //Initialize registers for shift operations "mov $0xAAAAAAAA, %%edi;" @@ -1538,6 +1561,7 @@ int asm_work_skl_corei_fma_1t(unsigned long long addrMem, unsigned long long add "vfmadd231pd %%ymm10, %%ymm0, %%ymm9; vfmadd231pd %%ymm2, %%ymm1, %%ymm11; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only "vfmadd231pd 64(%%rbx), %%ymm0, %%ymm10; vfmadd231pd 96(%%rbx), %%ymm1, %%ymm12; vmovapd %%ymm10, 32(%%rbx); add $128, %%rbx; " // 2 L1 loads, L1 store "vfmadd231pd 64(%%rbx), %%ymm0, %%ymm2; vfmadd231pd 96(%%rbx), %%ymm1, %%ymm12; vmovapd %%ymm2, 32(%%rbx); add $128, %%rbx; " // 2 L1 loads, L1 store + "movq %%mm0, %%r13;" // restore iteration counter //reset RAM counter "sub $1, %%r12;" "jnz _work_no_ram_reset_skl_corei_fma_1t;" @@ -1545,6 +1569,7 @@ int asm_work_skl_corei_fma_1t(unsigned long long addrMem, unsigned long long add "mov %%rax, %%r9;" "add $1572864, %%r9;" "_work_no_ram_reset_skl_corei_fma_1t:" + "inc %%r13;" // increment iteration counter //reset L2-Cache counter "sub $1, %%r10;" "jnz _work_no_L2_reset_skl_corei_fma_1t;" @@ -1552,6 +1577,7 @@ int asm_work_skl_corei_fma_1t(unsigned long long addrMem, unsigned long long add "mov %%rax, %%rcx;" "add $32768, %%rcx;" "_work_no_L2_reset_skl_corei_fma_1t:" + "movq %%r13, %%mm0;" // store iteration counter //reset L3-Cache counter "sub $1, %%r11;" "jnz _work_no_L3_reset_skl_corei_fma_1t;" @@ -1560,24 +1586,45 @@ int asm_work_skl_corei_fma_1t(unsigned long long addrMem, unsigned long long add "add $262144, %%r8;" "_work_no_L3_reset_skl_corei_fma_1t:" "mov %%rax, %%rbx;" - "mov (%%r15), %%r13;" - "test $1, %%r13;" + "testq $1, (%%r15);" "jnz _work_loop_skl_corei_fma_1t;" - : - : "a"(addrMem), "b"(addrHigh) - : "%rcx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%mm0, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } - int init_skl_corei_fma_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_skl_corei_fma_2t(unsigned long long addrMem) + + int init_skl_corei_fma_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_skl_corei_fma_2t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i=0;i<6670336;i++) *((double*)(addrMem+8*i)) = 0.25 + (double)(i%9267) * 0.24738995982e-4; + // lines with register operations + threaddata->flops+=40*16; // 2 256 bit FMA operations + + // lines with L1 operations + threaddata->flops+=78*16; // 2 256 bit FMA operations + + // lines with L2 operations + threaddata->flops+=18*8; // 1 256 bit FMA operation + + // lines with L3 operations + threaddata->flops+=5*8; // 1 256 bit FMA operation + + // lines with RAM operations + threaddata->flops+=3*16; // 2 256 bit FMA operations + threaddata->bytes=3*64; // 1 memory access + + threaddata->flops*=5; + threaddata->bytes*=5; + return EXIT_SUCCESS; } @@ -1588,10 +1635,10 @@ int init_skl_corei_fma_2t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_skl_corei_fma_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_skl_corei_fma_2t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_skl_corei_fma_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_skl_corei_fma_2t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -1606,12 +1653,14 @@ int asm_work_skl_corei_fma_2t(unsigned long long addrMem, unsigned long long add * - r13: register for temporary results * - r14: stores cacheline width as increment for buffer addresses * - r15: stores address of shared variable that controls load level + * - mm0: stores iteration counter * - rdx, rsi, rdi: registers for shift operations - * - mm*,xmm*,ymm*: data registers for SIMD instructions + * - xmm*,ymm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r15;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r15;" // store address of shared variable that controls load level + "movq %%rcx, %%mm0;" // store iteration counter "mov $64, %%r14;" // increment after each cache/memory access //Initialize registers for shift operations "mov $0xAAAAAAAA, %%edi;" @@ -2367,6 +2416,7 @@ int asm_work_skl_corei_fma_2t(unsigned long long addrMem, unsigned long long add "vfmadd231pd %%ymm10, %%ymm0, %%ymm9; vfmadd231pd %%ymm2, %%ymm1, %%ymm12; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only "vfmadd231pd 64(%%rbx), %%ymm0, %%ymm10; vfmadd231pd 96(%%rbx), %%ymm1, %%ymm13; vmovapd %%ymm10, 32(%%rbx); add $128, %%rbx; " // 2 L1 loads, L1 store "vfmadd231pd 64(%%rbx), %%ymm0, %%ymm2; vfmadd231pd 96(%%rbx), %%ymm1, %%ymm13; vmovapd %%ymm2, 32(%%rbx); add $128, %%rbx; " // 2 L1 loads, L1 store + "movq %%mm0, %%r13;" // restore iteration counter //reset RAM counter "sub $1, %%r12;" "jnz _work_no_ram_reset_skl_corei_fma_2t;" @@ -2374,6 +2424,7 @@ int asm_work_skl_corei_fma_2t(unsigned long long addrMem, unsigned long long add "mov %%rax, %%r9;" "add $786432, %%r9;" "_work_no_ram_reset_skl_corei_fma_2t:" + "inc %%r13;" // increment iteration counter //reset L2-Cache counter "sub $1, %%r10;" "jnz _work_no_L2_reset_skl_corei_fma_2t;" @@ -2381,6 +2432,7 @@ int asm_work_skl_corei_fma_2t(unsigned long long addrMem, unsigned long long add "mov %%rax, %%rcx;" "add $16384, %%rcx;" "_work_no_L2_reset_skl_corei_fma_2t:" + "movq %%r13, %%mm0;" // store iteration counter //reset L3-Cache counter "sub $1, %%r11;" "jnz _work_no_L3_reset_skl_corei_fma_2t;" @@ -2389,24 +2441,45 @@ int asm_work_skl_corei_fma_2t(unsigned long long addrMem, unsigned long long add "add $131072, %%r8;" "_work_no_L3_reset_skl_corei_fma_2t:" "mov %%rax, %%rbx;" - "mov (%%r15), %%r13;" - "test $1, %%r13;" + "testq $1, (%%r15);" "jnz _work_loop_skl_corei_fma_2t;" - : - : "a"(addrMem), "b"(addrHigh) - : "%rcx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%mm0, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } - int init_hsw_corei_fma_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_hsw_corei_fma_1t(unsigned long long addrMem) + + int init_hsw_corei_fma_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_hsw_corei_fma_1t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i=0;i<13340672;i++) *((double*)(addrMem+8*i)) = 0.25 + (double)(i%9267) * 0.24738995982e-4; + // lines with register operations + threaddata->flops+=40*16; // 2 256 bit FMA operations + + // lines with L1 operations + threaddata->flops+=90*8; // 1 256 bit FMA operation + + // lines with L2 operations + threaddata->flops+=9*8; // 1 256 bit FMA operation + + // lines with L3 operations + threaddata->flops+=3*8; // 1 256 bit FMA operation + + // lines with RAM operations + threaddata->flops+=2*16; // 2 256 bit FMA operations + threaddata->bytes=2*64; // 1 memory access + + threaddata->flops*=10; + threaddata->bytes*=10; + return EXIT_SUCCESS; } @@ -2417,10 +2490,10 @@ int init_hsw_corei_fma_1t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_hsw_corei_fma_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_hsw_corei_fma_1t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_hsw_corei_fma_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_hsw_corei_fma_1t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -2435,12 +2508,14 @@ int asm_work_hsw_corei_fma_1t(unsigned long long addrMem, unsigned long long add * - r13: register for temporary results * - r14: stores cacheline width as increment for buffer addresses * - r15: stores address of shared variable that controls load level + * - mm0: stores iteration counter * - rdx, rsi, rdi: registers for shift operations - * - mm*,xmm*,ymm*: data registers for SIMD instructions + * - xmm*,ymm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r15;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r15;" // store address of shared variable that controls load level + "movq %%rcx, %%mm0;" // store iteration counter "mov $64, %%r14;" // increment after each cache/memory access //Initialize registers for shift operations "mov $0xAAAAAAAA, %%edi;" @@ -3916,6 +3991,7 @@ int asm_work_hsw_corei_fma_1t(unsigned long long addrMem, unsigned long long add "vfmadd231pd %%ymm10, %%ymm0, %%ymm9; vfmadd231pd %%ymm2, %%ymm1, %%ymm11; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only "vmovapd %%xmm10, 64(%%rbx); vfmadd231pd 32(%%rbx), %%ymm0, %%ymm10; shr $1, %%esi; add %%r14, %%rbx; " // L1 load, L1 store "vmovapd %%xmm2, 64(%%rbx); vfmadd231pd 32(%%rbx), %%ymm0, %%ymm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load, L1 store + "movq %%mm0, %%r13;" // restore iteration counter //reset RAM counter "sub $1, %%r12;" "jnz _work_no_ram_reset_hsw_corei_fma_1t;" @@ -3923,6 +3999,7 @@ int asm_work_hsw_corei_fma_1t(unsigned long long addrMem, unsigned long long add "mov %%rax, %%r9;" "add $1572864, %%r9;" "_work_no_ram_reset_hsw_corei_fma_1t:" + "inc %%r13;" // increment iteration counter //reset L2-Cache counter "sub $1, %%r10;" "jnz _work_no_L2_reset_hsw_corei_fma_1t;" @@ -3930,6 +4007,7 @@ int asm_work_hsw_corei_fma_1t(unsigned long long addrMem, unsigned long long add "mov %%rax, %%rcx;" "add $32768, %%rcx;" "_work_no_L2_reset_hsw_corei_fma_1t:" + "movq %%r13, %%mm0;" // store iteration counter //reset L3-Cache counter "sub $1, %%r11;" "jnz _work_no_L3_reset_hsw_corei_fma_1t;" @@ -3938,24 +4016,45 @@ int asm_work_hsw_corei_fma_1t(unsigned long long addrMem, unsigned long long add "add $262144, %%r8;" "_work_no_L3_reset_hsw_corei_fma_1t:" "mov %%rax, %%rbx;" - "mov (%%r15), %%r13;" - "test $1, %%r13;" + "testq $1, (%%r15);" "jnz _work_loop_hsw_corei_fma_1t;" - : - : "a"(addrMem), "b"(addrHigh) - : "%rcx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%mm0, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } - int init_hsw_corei_fma_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_hsw_corei_fma_2t(unsigned long long addrMem) + + int init_hsw_corei_fma_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_hsw_corei_fma_2t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i=0;i<6670336;i++) *((double*)(addrMem+8*i)) = 0.25 + (double)(i%9267) * 0.24738995982e-4; + // lines with register operations + threaddata->flops+=40*16; // 2 256 bit FMA operations + + // lines with L1 operations + threaddata->flops+=90*8; // 1 256 bit FMA operation + + // lines with L2 operations + threaddata->flops+=9*8; // 1 256 bit FMA operation + + // lines with L3 operations + threaddata->flops+=3*8; // 1 256 bit FMA operation + + // lines with RAM operations + threaddata->flops+=2*16; // 2 256 bit FMA operations + threaddata->bytes=2*64; // 1 memory access + + threaddata->flops*=5; + threaddata->bytes*=5; + return EXIT_SUCCESS; } @@ -3966,10 +4065,10 @@ int init_hsw_corei_fma_2t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_hsw_corei_fma_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_hsw_corei_fma_2t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_hsw_corei_fma_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_hsw_corei_fma_2t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -3984,12 +4083,14 @@ int asm_work_hsw_corei_fma_2t(unsigned long long addrMem, unsigned long long add * - r13: register for temporary results * - r14: stores cacheline width as increment for buffer addresses * - r15: stores address of shared variable that controls load level + * - mm0: stores iteration counter * - rdx, rsi, rdi: registers for shift operations - * - mm*,xmm*,ymm*: data registers for SIMD instructions + * - xmm*,ymm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r15;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r15;" // store address of shared variable that controls load level + "movq %%rcx, %%mm0;" // store iteration counter "mov $64, %%r14;" // increment after each cache/memory access //Initialize registers for shift operations "mov $0xAAAAAAAA, %%edi;" @@ -4745,6 +4846,7 @@ int asm_work_hsw_corei_fma_2t(unsigned long long addrMem, unsigned long long add "vfmadd231pd %%ymm10, %%ymm0, %%ymm9; vfmadd231pd %%ymm2, %%ymm1, %%ymm12; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only "vmovapd %%xmm10, 64(%%rbx); vfmadd231pd 32(%%rbx), %%ymm0, %%ymm10; shr $1, %%esi; add %%r14, %%rbx; " // L1 load, L1 store "vmovapd %%xmm2, 64(%%rbx); vfmadd231pd 32(%%rbx), %%ymm0, %%ymm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load, L1 store + "movq %%mm0, %%r13;" // restore iteration counter //reset RAM counter "sub $1, %%r12;" "jnz _work_no_ram_reset_hsw_corei_fma_2t;" @@ -4752,6 +4854,7 @@ int asm_work_hsw_corei_fma_2t(unsigned long long addrMem, unsigned long long add "mov %%rax, %%r9;" "add $786432, %%r9;" "_work_no_ram_reset_hsw_corei_fma_2t:" + "inc %%r13;" // increment iteration counter //reset L2-Cache counter "sub $1, %%r10;" "jnz _work_no_L2_reset_hsw_corei_fma_2t;" @@ -4759,6 +4862,7 @@ int asm_work_hsw_corei_fma_2t(unsigned long long addrMem, unsigned long long add "mov %%rax, %%rcx;" "add $16384, %%rcx;" "_work_no_L2_reset_hsw_corei_fma_2t:" + "movq %%r13, %%mm0;" // store iteration counter //reset L3-Cache counter "sub $1, %%r11;" "jnz _work_no_L3_reset_hsw_corei_fma_2t;" @@ -4767,24 +4871,45 @@ int asm_work_hsw_corei_fma_2t(unsigned long long addrMem, unsigned long long add "add $131072, %%r8;" "_work_no_L3_reset_hsw_corei_fma_2t:" "mov %%rax, %%rbx;" - "mov (%%r15), %%r13;" - "test $1, %%r13;" + "testq $1, (%%r15);" "jnz _work_loop_hsw_corei_fma_2t;" - : - : "a"(addrMem), "b"(addrHigh) - : "%rcx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%mm0, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } - int init_hsw_xeonep_fma_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_hsw_xeonep_fma_1t(unsigned long long addrMem) + + int init_hsw_xeonep_fma_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_hsw_xeonep_fma_1t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i=0;i<13471744;i++) *((double*)(addrMem+8*i)) = 0.25 + (double)(i%9267) * 0.24738995982e-4; + // lines with register operations + threaddata->flops+=35*16; // 2 256 bit FMA operations + + // lines with L1 operations + threaddata->flops+=79*8; // 1 256 bit FMA operation + + // lines with L2 operations + threaddata->flops+=9*8; // 1 256 bit FMA operation + + // lines with L3 operations + threaddata->flops+=1*8; // 1 256 bit FMA operation + + // lines with RAM operations + threaddata->flops+=2*16; // 2 256 bit FMA operations + threaddata->bytes=2*64; // 1 memory access + + threaddata->flops*=12; + threaddata->bytes*=12; + return EXIT_SUCCESS; } @@ -4795,10 +4920,10 @@ int init_hsw_xeonep_fma_1t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_hsw_xeonep_fma_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_hsw_xeonep_fma_1t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_hsw_xeonep_fma_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_hsw_xeonep_fma_1t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -4813,12 +4938,14 @@ int asm_work_hsw_xeonep_fma_1t(unsigned long long addrMem, unsigned long long ad * - r13: register for temporary results * - r14: stores cacheline width as increment for buffer addresses * - r15: stores address of shared variable that controls load level + * - mm0: stores iteration counter * - rdx, rsi, rdi: registers for shift operations - * - mm*,xmm*,ymm*: data registers for SIMD instructions + * - xmm*,ymm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r15;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r15;" // store address of shared variable that controls load level + "movq %%rcx, %%mm0;" // store iteration counter "mov $64, %%r14;" // increment after each cache/memory access //Initialize registers for shift operations "mov $0xAAAAAAAA, %%edi;" @@ -6366,6 +6493,7 @@ int asm_work_hsw_xeonep_fma_1t(unsigned long long addrMem, unsigned long long ad "vfmadd231pd %%ymm10, %%ymm0, %%ymm9; vfmadd231pd %%ymm2, %%ymm1, %%ymm13; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only "vmovapd %%xmm10, 64(%%rbx); vfmadd231pd 32(%%rbx), %%ymm0, %%ymm10; shr $1, %%esi; add %%r14, %%rbx; " // L1 load, L1 store "vmovapd %%xmm2, 64(%%rbx); vfmadd231pd 32(%%rbx), %%ymm0, %%ymm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load, L1 store + "movq %%mm0, %%r13;" // restore iteration counter //reset RAM counter "sub $1, %%r12;" "jnz _work_no_ram_reset_hsw_xeonep_fma_1t;" @@ -6373,6 +6501,7 @@ int asm_work_hsw_xeonep_fma_1t(unsigned long long addrMem, unsigned long long ad "mov %%rax, %%r9;" "add $2621440, %%r9;" "_work_no_ram_reset_hsw_xeonep_fma_1t:" + "inc %%r13;" // increment iteration counter //reset L2-Cache counter "sub $1, %%r10;" "jnz _work_no_L2_reset_hsw_xeonep_fma_1t;" @@ -6380,6 +6509,7 @@ int asm_work_hsw_xeonep_fma_1t(unsigned long long addrMem, unsigned long long ad "mov %%rax, %%rcx;" "add $32768, %%rcx;" "_work_no_L2_reset_hsw_xeonep_fma_1t:" + "movq %%r13, %%mm0;" // store iteration counter //reset L3-Cache counter "sub $1, %%r11;" "jnz _work_no_L3_reset_hsw_xeonep_fma_1t;" @@ -6388,24 +6518,45 @@ int asm_work_hsw_xeonep_fma_1t(unsigned long long addrMem, unsigned long long ad "add $262144, %%r8;" "_work_no_L3_reset_hsw_xeonep_fma_1t:" "mov %%rax, %%rbx;" - "mov (%%r15), %%r13;" - "test $1, %%r13;" + "testq $1, (%%r15);" "jnz _work_loop_hsw_xeonep_fma_1t;" - : - : "a"(addrMem), "b"(addrHigh) - : "%rcx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%mm0, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } - int init_hsw_xeonep_fma_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_hsw_xeonep_fma_2t(unsigned long long addrMem) + + int init_hsw_xeonep_fma_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_hsw_xeonep_fma_2t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i=0;i<6735872;i++) *((double*)(addrMem+8*i)) = 0.25 + (double)(i%9267) * 0.24738995982e-4; + // lines with register operations + threaddata->flops+=35*16; // 2 256 bit FMA operations + + // lines with L1 operations + threaddata->flops+=79*8; // 1 256 bit FMA operation + + // lines with L2 operations + threaddata->flops+=9*8; // 1 256 bit FMA operation + + // lines with L3 operations + threaddata->flops+=1*8; // 1 256 bit FMA operation + + // lines with RAM operations + threaddata->flops+=2*16; // 2 256 bit FMA operations + threaddata->bytes=2*64; // 1 memory access + + threaddata->flops*=6; + threaddata->bytes*=6; + return EXIT_SUCCESS; } @@ -6416,10 +6567,10 @@ int init_hsw_xeonep_fma_2t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_hsw_xeonep_fma_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_hsw_xeonep_fma_2t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_hsw_xeonep_fma_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_hsw_xeonep_fma_2t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -6434,12 +6585,14 @@ int asm_work_hsw_xeonep_fma_2t(unsigned long long addrMem, unsigned long long ad * - r13: register for temporary results * - r14: stores cacheline width as increment for buffer addresses * - r15: stores address of shared variable that controls load level + * - mm0: stores iteration counter * - rdx, rsi, rdi: registers for shift operations - * - mm*,xmm*,ymm*: data registers for SIMD instructions + * - xmm*,ymm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r15;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r15;" // store address of shared variable that controls load level + "movq %%rcx, %%mm0;" // store iteration counter "mov $64, %%r14;" // increment after each cache/memory access //Initialize registers for shift operations "mov $0xAAAAAAAA, %%edi;" @@ -7231,6 +7384,7 @@ int asm_work_hsw_xeonep_fma_2t(unsigned long long addrMem, unsigned long long ad "vfmadd231pd %%ymm10, %%ymm0, %%ymm9; vfmadd231pd %%ymm2, %%ymm1, %%ymm13; shr $1, %%edi; xor %%rdx, %%r13; " // REG ops only "vmovapd %%xmm10, 64(%%rbx); vfmadd231pd 32(%%rbx), %%ymm0, %%ymm10; shr $1, %%esi; add %%r14, %%rbx; " // L1 load, L1 store "vmovapd %%xmm2, 64(%%rbx); vfmadd231pd 32(%%rbx), %%ymm0, %%ymm2; shr $1, %%edx; add %%r14, %%rbx; " // L1 load, L1 store + "movq %%mm0, %%r13;" // restore iteration counter //reset RAM counter "sub $1, %%r12;" "jnz _work_no_ram_reset_hsw_xeonep_fma_2t;" @@ -7238,6 +7392,7 @@ int asm_work_hsw_xeonep_fma_2t(unsigned long long addrMem, unsigned long long ad "mov %%rax, %%r9;" "add $1310720, %%r9;" "_work_no_ram_reset_hsw_xeonep_fma_2t:" + "inc %%r13;" // increment iteration counter //reset L2-Cache counter "sub $1, %%r10;" "jnz _work_no_L2_reset_hsw_xeonep_fma_2t;" @@ -7245,6 +7400,7 @@ int asm_work_hsw_xeonep_fma_2t(unsigned long long addrMem, unsigned long long ad "mov %%rax, %%rcx;" "add $16384, %%rcx;" "_work_no_L2_reset_hsw_xeonep_fma_2t:" + "movq %%r13, %%mm0;" // store iteration counter //reset L3-Cache counter "sub $1, %%r11;" "jnz _work_no_L3_reset_hsw_xeonep_fma_2t;" @@ -7253,12 +7409,12 @@ int asm_work_hsw_xeonep_fma_2t(unsigned long long addrMem, unsigned long long ad "add $131072, %%r8;" "_work_no_L3_reset_hsw_xeonep_fma_2t:" "mov %%rax, %%rbx;" - "mov (%%r15), %%r13;" - "test $1, %%r13;" + "testq $1, (%%r15);" "jnz _work_loop_hsw_xeonep_fma_2t;" - : - : "a"(addrMem), "b"(addrHigh) - : "%rcx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%mm0, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rdx", "%rsi", "%rdi", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } diff --git a/generic.c b/generic.c index 7c3ed22f..f0efc62e 100644 --- a/generic.c +++ b/generic.c @@ -50,11 +50,14 @@ /* use old memcpy to avoid GLIBC 2.14 dependency */ __asm__(".symver memcpy, memcpy@GLIBC_2.2.5"); - /* buffer for some generic implementations */ +/* buffer for some generic implementations */ // TODO remove global variables to allow thread safe execution of detection static char output[_HW_DETECT_MAX_OUTPUT]; static char path[_HW_DETECT_MAX_OUTPUT]; +/* avoid multiple executions of the corresponding functions */ +static int num_packages_sav = 0, num_cores_per_package_sav = 0, num_threads_per_core_sav = 0, num_threads_per_package_sav = 0; + /** * list element for counting unique package_ids, core_ids etc. */ @@ -309,28 +312,22 @@ void generic_get_architecture(char* arch) */ int get_pkg(int cpu) { - int pkg=0; - char buffer[_HW_DETECT_MAX_OUTPUT]; - - if ((num_cpus() == 1) || (num_packages() == 1)) { return 0; } + int pkg=-1; + char buffer[10]; if (cpu == -1) { cpu = get_cpu(); } if (cpu != -1) { - sprintf(path, "/sys/devices/system/cpu/cpu%i/topology/physical_package_id", cpu); + if( read_file(path, buffer, sizeof(buffer)) ) pkg = atoi(buffer); - if( !read_file(path, buffer, sizeof(buffer)) ) { - pkg = -1; - } - else { - pkg = atoi(buffer); - } - + /* fallbacks if sysfs is not working */ if (pkg == -1) { + /* assume 0 if there is only one CPU or only one package */ + if ((num_cpus() == 1) || (num_packages() == 1)) { return 0; } /* get the physical package id from /proc/cpuinfo */ - if(!get_proc_cpuinfo_data("physical id", buffer, cpu)) { pkg = atoi(buffer); } + else if(!get_proc_cpuinfo_data("physical id", buffer, cpu)) { pkg = atoi(buffer); } /* if the number of cpus equals the number of packages assume pkg_id = cpu_id*/ else if (num_cpus() == num_packages()) { pkg = cpu; } /* if there is only one core per package assume pkg_id = core_id */ @@ -342,6 +339,7 @@ int get_pkg(int cpu) without correct topology information in sysfs*/ } } + return pkg; } @@ -353,28 +351,25 @@ int get_core_id(int cpu) int core=-1; char buffer[10]; - if (num_cpus() == 1) { return 0; } - if (cpu == -1) { cpu = get_cpu(); } if (cpu != -1) { sprintf(path, "/sys/devices/system/cpu/cpu%i/topology/core_id", cpu); + if(read_file(path, buffer, sizeof(buffer))) core = atoi(buffer); - if(!read_file(path, buffer, sizeof(buffer))) { - core = -1; - } - else { - core = atoi(buffer); + /* fallbacks if sysfs is not working */ + if (core == -1) + { + /* assume 0 if there is only one CPU */ + if (num_cpus() == 1) { return 0; } + /* if each package contains only one cpu assume core_id = package_id = cpu_id */ + else if (num_cores_per_package() == 1) { core = 0; } + + /* NOTE core_id can't be determined without correct topology information in sysfs if there are multiple cores per package + TODO /proc/cpuinfo */ } } - if (core == -1) - { - /* if each package contains only one cpu assume core_id = package_id = cpu_id */ - if (num_cores_per_package() == 1) { core = 0; } - /* NOTE core_id can't be determined without correct topology information in sysfs if there are multiple cores per package - TODO /proc/cpuinfo */ - } return core; } @@ -464,7 +459,7 @@ void init_cpuinfo(cpu_info_t *cpuinfo,int print) cpuinfo->clockrate = get_cpu_clockrate(1, 0); /* setup supported feature list*/ - if(!strcmp(cpuinfo->architecture,"x86_64")) cpuinfo->features |=X86_64; + if(!strcmp(cpuinfo->architecture,"x86_64")) cpuinfo->features |= X86_64; if (feature_available("SMT")) cpuinfo->features |= SMT; if (feature_available("FPU")) cpuinfo->features |= FPU; if (feature_available("MMX")) cpuinfo->features |= MMX; @@ -479,8 +474,10 @@ void init_cpuinfo(cpu_info_t *cpuinfo,int print) if (feature_available("ABM")) cpuinfo->features |= ABM; if (feature_available("POPCNT")) cpuinfo->features |= POPCNT; if (feature_available("AVX")) cpuinfo->features |= AVX; + if (feature_available("AVX2")) cpuinfo->features |= AVX2; if (feature_available("FMA")) cpuinfo->features |= FMA; if (feature_available("AES")) cpuinfo->features |= AES; + if (feature_available("AVX512")) cpuinfo->features |= AVX512; /* determine cache details */ for (i=0; i<(unsigned int)num_caches(0); i++) @@ -543,6 +540,8 @@ void init_cpuinfo(cpu_info_t *cpuinfo,int print) if(cpuinfo->features&SSE4A) printf(" SSE4A"); if(cpuinfo->features&POPCNT) printf(" POPCNT"); if(cpuinfo->features&AVX) printf(" AVX"); + if(cpuinfo->features&AVX2) printf(" AVX2"); + if(cpuinfo->features&AVX512) printf(" AVX512"); if(cpuinfo->features&FMA) printf(" FMA"); if(cpuinfo->features&AES) printf(" AES"); if(cpuinfo->features&SMT) printf(" SMT"); @@ -1020,11 +1019,13 @@ int generic_cacheline_length(int cpu, int id) { int generic_num_packages() { struct dirent **namelist; - int ndir, m, num = -1; + int ndir, m; char tmppath[_HW_DETECT_MAX_OUTPUT]; char buf[20]; id_le * pkg_id_list = NULL; + if (num_packages_sav != 0) return num_packages_sav; + num_packages_sav = -1; strcpy(path, "/sys/devices/system/cpu/"); ndir = scandir(path, &namelist, 0, 0); @@ -1049,20 +1050,23 @@ int generic_num_packages() free(namelist[ndir]); } free(namelist); - num = id_total_count(pkg_id_list); + num_packages_sav = id_total_count(pkg_id_list); free_id_list(&pkg_id_list); } - return num; + return num_packages_sav; } int generic_num_cores_per_package() { struct dirent **namelist; - int ndir, m, n, num = 0, pkg_id_tocount = -1; + int ndir, m, n, pkg_id_tocount = -1; char tmppath[_HW_DETECT_MAX_OUTPUT]; char buf[20]; id_le *core_id_list = NULL; + if (num_cores_per_package_sav != 0) return num_cores_per_package_sav; + num_cores_per_package_sav=-1; + strcpy(path, "/sys/devices/system/cpu/"); ndir = scandir(path, &namelist, 0, 0); if(ndir >= 0) @@ -1099,22 +1103,25 @@ int generic_num_cores_per_package() free(namelist[ndir]); } free(namelist); - num = id_total_count(core_id_list); + num_cores_per_package_sav = id_total_count(core_id_list); free_id_list(&core_id_list); } - else return -1; + else num_cores_per_package_sav = -1; - if (num==0) return -1; - return num; + if (num_cores_per_package_sav == 0) num_cores_per_package_sav = -1; + + return num_cores_per_package_sav; } int generic_num_threads_per_core() { struct dirent **namelist; - int ndir, m, n, num = 0, pkg_id_tocount = -1, core_id_tocount = -1; + int ndir, m, n, pkg_id_tocount = -1, core_id_tocount = -1; char tmppath[_HW_DETECT_MAX_OUTPUT]; char buf[20]; + if (num_threads_per_core_sav != 0) return num_threads_per_core_sav; + strcpy(path, "/sys/devices/system/cpu/"); ndir = scandir(path, &namelist, 0, 0); if(ndir >= 0) @@ -1144,7 +1151,7 @@ int generic_num_threads_per_core() if(m == core_id_tocount && n == pkg_id_tocount) /*FIXME: only counts threads from the first core_id and package_id that are found, assumes that every core has the same amount of threads*/ { - num++; + num_threads_per_core_sav++; } } } @@ -1152,23 +1159,23 @@ int generic_num_threads_per_core() } free(namelist); } - else return -1; + else num_threads_per_core_sav = -1; - if (num == 0) num = generic_num_threads_per_package() / generic_num_cores_per_package(); - if (num != generic_num_threads_per_package() / generic_num_cores_per_package()) return -1; + if (num_threads_per_core_sav == 0) num_threads_per_core_sav = generic_num_threads_per_package() / generic_num_cores_per_package(); + if (num_threads_per_core_sav != generic_num_threads_per_package() / generic_num_cores_per_package()) num_threads_per_core_sav = -1; - return num; + return num_threads_per_core_sav; } int generic_num_threads_per_package() { struct dirent **namelist; - int ndir, m, num = 0, pkg_id_tocount = -1; + int ndir, m, pkg_id_tocount = -1; char tmppath[_HW_DETECT_MAX_OUTPUT]; char buf[20]; - /*TODO proc/cpuinfo*/ + if (num_threads_per_package_sav != 0) return num_threads_per_package_sav; strcpy(path, "/sys/devices/system/cpu/"); ndir = scandir(path, &namelist, 0, 0); @@ -1192,7 +1199,7 @@ int generic_num_threads_per_package() if(m == pkg_id_tocount) /*FIXME: only counts threads from first package_id that is found and assumes that every package has the same amount of threads*/ { - num++; + num_threads_per_package_sav++; } } } @@ -1200,20 +1207,21 @@ int generic_num_threads_per_package() } free(namelist); } - else return -1; + else num_threads_per_package_sav = -1; - if (num == 0) return -1; - return num; + if (num_threads_per_package_sav == 0) num_threads_per_package_sav = -1; + + return num_threads_per_package_sav; } /* see cpu.h */ #if defined (__ARCH_UNKNOWN) - /* - * use generic implementations for unknown architectures - */ +/* + * use generic implementations for unknown architectures + */ - void get_architecture(char * arch) { +void get_architecture(char * arch) { generic_get_architecture(arch); } diff --git a/help.c b/help.c index c2254618..40b9073f 100644 --- a/help.c +++ b/help.c @@ -42,8 +42,10 @@ void show_help(void) " -c | --copyright display copyright information\n" " -w | --warranty display warranty information\n" " -q | --quiet disable output to stdout\n" + " -r | --report display additional information (overridden by -q)\n" " -a | --avail list available functions\n" - " -i ID | --function=ID specify ID of the load-function to be used\n" + " -i ID | --function=ID specify integer ID of the load-function to be\n" + " used (as listed by --avail)\n" #ifdef CUDA " -f | --usegpufloat use single precision matrix multiplications instead of double\n" " -g | --gpus number of gpus to use (default: all)\n" @@ -61,10 +63,13 @@ void show_help(void) " high load is defined by -l\n" " will be overwriten if used with -s, -e and -n\n" " -n COUNT | --threads=COUNT specify the number of threads\n" + " cannot be combined with -b | --bind, which\n" + " implicitly specifies the number of threads\n" #if (defined(linux) || defined(__linux__)) && defined (AFFINITY) - " -b CPULIST | --bind=CPULIST select certain CPUs (overrides -n)\n" + " -b CPULIST | --bind=CPULIST select certain CPUs\n" " CPULIST format: \"x,y,z\", \"x-y\", \"x-y/step\",\n" " and any combination of the above\n" + " cannot be combined with -n | --threads\n" #endif "\n" "\nExamples:\n\n" diff --git a/main.c b/main.c index 5e9da302..50db75c1 100644 --- a/main.c +++ b/main.c @@ -48,6 +48,26 @@ #include "gpu.h" #endif +/* + * used for --bind option + */ +#define ADD_CPU_SET(cpu,cpuset) \ +do { \ + if (cpu_allowed(cpu)) { \ + CPU_SET(cpu, &cpuset); \ + } else { \ + if (cpu >= num_cpus() ) { \ + fprintf( stderr, "Error: The given bind argument (-b/--bind) includes CPU %d that is not available on this system.\n",cpu ); \ + } \ + else { \ + fprintf( stderr, "Error: The given bind argument (-b/--bind) cannot be implemented with the cpuset given from the OS\n" ); \ + fprintf( stderr, "This can be caused by the taskset tool, cgroups, the batch system, or similar mechanisms.\n" ); \ + fprintf( stderr, "Please fix the argument to match the restrictions.\n" ); \ + } \ + exit( EACCES ); \ + } \ +} while (0) + mydata_t *mdp; /* global data structure */ cpu_info_t *cpuinfo = NULL; /* data structure for hardware detection */ unsigned long long LOADVAR = LOAD_HIGH; /* shared variable that specifies load level */ @@ -78,6 +98,11 @@ long long unsigned int STARTPERIOD = 0, ENDPERIOD = 0, NUMPERIODSTEPS = 0; */ char *fsbind = NULL; +/* + * temporary variables + */ +int tmp1,tmp2; + /* * worker threads */ @@ -126,6 +151,23 @@ static void *init() exit(127); } + if (verbose) { + printf(" using %i threads\n", NUM_THREADS); + #if (defined(linux) || defined(__linux__)) && defined (AFFINITY) + for (i = 0; i < NUM_THREADS; i++){ + /* avoid multiple sysfs accesses */ + tmp1=get_core_id(cpu_bind[i]); + tmp2=get_pkg(cpu_bind[i]); + if ((tmp1 != -1) && (tmp2 != -1)){ + printf(" - Thread %i runs on CPU %llu, core %i in package: %i\n", + i, cpu_bind[i], tmp1, tmp2); + } + } + #endif + printf("\n"); + fflush(stdout); + } + // create worker threads for (t = 0; t < NUM_THREADS; t++) { mdp->ack = 0; @@ -133,6 +175,9 @@ static void *init() mdp->threaddata[t].cpu_id = cpu_bind[t]; mdp->threaddata[t].data = mdp; mdp->threaddata[t].buffersizeMem = BUFFERSIZEMEM; + mdp->threaddata[t].iterations = 0; + mdp->threaddata[t].flops = 0; + mdp->threaddata[t].bytes = 0; mdp->threaddata[t].alignment = ALIGNMENT; mdp->threaddata[t].FUNCTION = FUNCTION; mdp->threaddata[t].period = PERIOD; @@ -159,20 +204,6 @@ static void *init() } mdp->ack = 0; - if (verbose) { - printf(" using %i threads\n", NUM_THREADS); - #if (defined(linux) || defined(__linux__)) && defined (AFFINITY) - for (i = 0; i < NUM_THREADS; i++){ - if ((get_pkg(cpu_bind[i]) != -1) && (get_core_id(cpu_bind[i]) != -1)){ - printf(" - Thread %i runs on CPU %llu, core %i in package: %i\n", - i, cpu_bind[i], get_core_id(cpu_bind[i]),get_pkg(cpu_bind[i])); - } - } - #endif - printf("\n"); - fflush(stdout); - } - return (void *) mdp; } @@ -183,36 +214,38 @@ static void list_functions(){ printf("\n available load-functions:\n"); printf(" ID | NAME | available on this system\n"); printf(" ----------------------------------------------------------------\n"); - if (feature_available("FMA")) printf(" %4.4s | %.30s | yes\n","1","FUNC_SKL_COREI_FMA_1T "); - else printf(" %4.4s | %.30s | no\n","1","FUNC_SKL_COREI_FMA_1T "); - if (feature_available("FMA")) printf(" %4.4s | %.30s | yes\n","2","FUNC_SKL_COREI_FMA_2T "); - else printf(" %4.4s | %.30s | no\n","2","FUNC_SKL_COREI_FMA_2T "); - if (feature_available("FMA")) printf(" %4.4s | %.30s | yes\n","3","FUNC_HSW_COREI_FMA_1T "); - else printf(" %4.4s | %.30s | no\n","3","FUNC_HSW_COREI_FMA_1T "); - if (feature_available("FMA")) printf(" %4.4s | %.30s | yes\n","4","FUNC_HSW_COREI_FMA_2T "); - else printf(" %4.4s | %.30s | no\n","4","FUNC_HSW_COREI_FMA_2T "); - if (feature_available("FMA")) printf(" %4.4s | %.30s | yes\n","5","FUNC_HSW_XEONEP_FMA_1T "); - else printf(" %4.4s | %.30s | no\n","5","FUNC_HSW_XEONEP_FMA_1T "); - if (feature_available("FMA")) printf(" %4.4s | %.30s | yes\n","6","FUNC_HSW_XEONEP_FMA_2T "); - else printf(" %4.4s | %.30s | no\n","6","FUNC_HSW_XEONEP_FMA_2T "); - if (feature_available("AVX")) printf(" %4.4s | %.30s | yes\n","7","FUNC_SNB_COREI_AVX_1T "); - else printf(" %4.4s | %.30s | no\n","7","FUNC_SNB_COREI_AVX_1T "); - if (feature_available("AVX")) printf(" %4.4s | %.30s | yes\n","8","FUNC_SNB_COREI_AVX_2T "); - else printf(" %4.4s | %.30s | no\n","8","FUNC_SNB_COREI_AVX_2T "); - if (feature_available("AVX")) printf(" %4.4s | %.30s | yes\n","9","FUNC_SNB_XEONEP_AVX_1T "); - else printf(" %4.4s | %.30s | no\n","9","FUNC_SNB_XEONEP_AVX_1T "); - if (feature_available("AVX")) printf(" %4.4s | %.30s | yes\n","10","FUNC_SNB_XEONEP_AVX_2T "); - else printf(" %4.4s | %.30s | no\n","10","FUNC_SNB_XEONEP_AVX_2T "); - if (feature_available("SSE2")) printf(" %4.4s | %.30s | yes\n","11","FUNC_NHM_COREI_SSE2_1T "); - else printf(" %4.4s | %.30s | no\n","11","FUNC_NHM_COREI_SSE2_1T "); - if (feature_available("SSE2")) printf(" %4.4s | %.30s | yes\n","12","FUNC_NHM_COREI_SSE2_2T "); - else printf(" %4.4s | %.30s | no\n","12","FUNC_NHM_COREI_SSE2_2T "); - if (feature_available("SSE2")) printf(" %4.4s | %.30s | yes\n","13","FUNC_NHM_XEONEP_SSE2_1T "); - else printf(" %4.4s | %.30s | no\n","13","FUNC_NHM_XEONEP_SSE2_1T "); - if (feature_available("SSE2")) printf(" %4.4s | %.30s | yes\n","14","FUNC_NHM_XEONEP_SSE2_2T "); - else printf(" %4.4s | %.30s | no\n","14","FUNC_NHM_XEONEP_SSE2_2T "); - if (feature_available("FMA4")) printf(" %4.4s | %.30s | yes\n","15","FUNC_BLD_OPTERON_FMA4_1T "); - else printf(" %4.4s | %.30s | no\n","15","FUNC_BLD_OPTERON_FMA4_1T "); + if (feature_available("AVX512")) printf(" %4.4s | %.30s | yes\n","1","FUNC_KNL_XEONPHI_AVX512_4T "); + else printf(" %4.4s | %.30s | no\n","1","FUNC_KNL_XEONPHI_AVX512_4T "); + if (feature_available("FMA")) printf(" %4.4s | %.30s | yes\n","2","FUNC_SKL_COREI_FMA_1T "); + else printf(" %4.4s | %.30s | no\n","2","FUNC_SKL_COREI_FMA_1T "); + if (feature_available("FMA")) printf(" %4.4s | %.30s | yes\n","3","FUNC_SKL_COREI_FMA_2T "); + else printf(" %4.4s | %.30s | no\n","3","FUNC_SKL_COREI_FMA_2T "); + if (feature_available("FMA")) printf(" %4.4s | %.30s | yes\n","4","FUNC_HSW_COREI_FMA_1T "); + else printf(" %4.4s | %.30s | no\n","4","FUNC_HSW_COREI_FMA_1T "); + if (feature_available("FMA")) printf(" %4.4s | %.30s | yes\n","5","FUNC_HSW_COREI_FMA_2T "); + else printf(" %4.4s | %.30s | no\n","5","FUNC_HSW_COREI_FMA_2T "); + if (feature_available("FMA")) printf(" %4.4s | %.30s | yes\n","6","FUNC_HSW_XEONEP_FMA_1T "); + else printf(" %4.4s | %.30s | no\n","6","FUNC_HSW_XEONEP_FMA_1T "); + if (feature_available("FMA")) printf(" %4.4s | %.30s | yes\n","7","FUNC_HSW_XEONEP_FMA_2T "); + else printf(" %4.4s | %.30s | no\n","7","FUNC_HSW_XEONEP_FMA_2T "); + if (feature_available("AVX")) printf(" %4.4s | %.30s | yes\n","8","FUNC_SNB_COREI_AVX_1T "); + else printf(" %4.4s | %.30s | no\n","8","FUNC_SNB_COREI_AVX_1T "); + if (feature_available("AVX")) printf(" %4.4s | %.30s | yes\n","9","FUNC_SNB_COREI_AVX_2T "); + else printf(" %4.4s | %.30s | no\n","9","FUNC_SNB_COREI_AVX_2T "); + if (feature_available("AVX")) printf(" %4.4s | %.30s | yes\n","10","FUNC_SNB_XEONEP_AVX_1T "); + else printf(" %4.4s | %.30s | no\n","10","FUNC_SNB_XEONEP_AVX_1T "); + if (feature_available("AVX")) printf(" %4.4s | %.30s | yes\n","11","FUNC_SNB_XEONEP_AVX_2T "); + else printf(" %4.4s | %.30s | no\n","11","FUNC_SNB_XEONEP_AVX_2T "); + if (feature_available("SSE2")) printf(" %4.4s | %.30s | yes\n","12","FUNC_NHM_COREI_SSE2_1T "); + else printf(" %4.4s | %.30s | no\n","12","FUNC_NHM_COREI_SSE2_1T "); + if (feature_available("SSE2")) printf(" %4.4s | %.30s | yes\n","13","FUNC_NHM_COREI_SSE2_2T "); + else printf(" %4.4s | %.30s | no\n","13","FUNC_NHM_COREI_SSE2_2T "); + if (feature_available("SSE2")) printf(" %4.4s | %.30s | yes\n","14","FUNC_NHM_XEONEP_SSE2_1T "); + else printf(" %4.4s | %.30s | no\n","14","FUNC_NHM_XEONEP_SSE2_1T "); + if (feature_available("SSE2")) printf(" %4.4s | %.30s | yes\n","15","FUNC_NHM_XEONEP_SSE2_2T "); + else printf(" %4.4s | %.30s | no\n","15","FUNC_NHM_XEONEP_SSE2_2T "); + if (feature_available("FMA4")) printf(" %4.4s | %.30s | yes\n","16","FUNC_BLD_OPTERON_FMA4_1T "); + else printf(" %4.4s | %.30s | no\n","16","FUNC_BLD_OPTERON_FMA4_1T "); return; } @@ -222,93 +255,99 @@ static int get_function(unsigned int id){ switch(id){ case 1: - if (feature_available("FMA")) func = FUNC_SKL_COREI_FMA_1T; + if (feature_available("AVX512")) func = FUNC_KNL_XEONPHI_AVX512_4T; else{ - fprintf(stderr, "\nError: Function 1 (\"FUNC_SKL_COREI_FMA_1T\") requires FMA, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 1 (\"FUNC_KNL_XEONPHI_AVX512_4T\") requires AVX512, which is not supported by the processor.\n\n"); } break; case 2: - if (feature_available("FMA")) func = FUNC_SKL_COREI_FMA_2T; + if (feature_available("FMA")) func = FUNC_SKL_COREI_FMA_1T; else{ - fprintf(stderr, "\nError: Function 2 (\"FUNC_SKL_COREI_FMA_2T\") requires FMA, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 2 (\"FUNC_SKL_COREI_FMA_1T\") requires FMA, which is not supported by the processor.\n\n"); } break; case 3: - if (feature_available("FMA")) func = FUNC_HSW_COREI_FMA_1T; + if (feature_available("FMA")) func = FUNC_SKL_COREI_FMA_2T; else{ - fprintf(stderr, "\nError: Function 3 (\"FUNC_HSW_COREI_FMA_1T\") requires FMA, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 3 (\"FUNC_SKL_COREI_FMA_2T\") requires FMA, which is not supported by the processor.\n\n"); } break; case 4: - if (feature_available("FMA")) func = FUNC_HSW_COREI_FMA_2T; + if (feature_available("FMA")) func = FUNC_HSW_COREI_FMA_1T; else{ - fprintf(stderr, "\nError: Function 4 (\"FUNC_HSW_COREI_FMA_2T\") requires FMA, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 4 (\"FUNC_HSW_COREI_FMA_1T\") requires FMA, which is not supported by the processor.\n\n"); } break; case 5: - if (feature_available("FMA")) func = FUNC_HSW_XEONEP_FMA_1T; + if (feature_available("FMA")) func = FUNC_HSW_COREI_FMA_2T; else{ - fprintf(stderr, "\nError: Function 5 (\"FUNC_HSW_XEONEP_FMA_1T\") requires FMA, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 5 (\"FUNC_HSW_COREI_FMA_2T\") requires FMA, which is not supported by the processor.\n\n"); } break; case 6: - if (feature_available("FMA")) func = FUNC_HSW_XEONEP_FMA_2T; + if (feature_available("FMA")) func = FUNC_HSW_XEONEP_FMA_1T; else{ - fprintf(stderr, "\nError: Function 6 (\"FUNC_HSW_XEONEP_FMA_2T\") requires FMA, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 6 (\"FUNC_HSW_XEONEP_FMA_1T\") requires FMA, which is not supported by the processor.\n\n"); } break; case 7: - if (feature_available("AVX")) func = FUNC_SNB_COREI_AVX_1T; + if (feature_available("FMA")) func = FUNC_HSW_XEONEP_FMA_2T; else{ - fprintf(stderr, "\nError: Function 7 (\"FUNC_SNB_COREI_AVX_1T\") requires AVX, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 7 (\"FUNC_HSW_XEONEP_FMA_2T\") requires FMA, which is not supported by the processor.\n\n"); } break; case 8: - if (feature_available("AVX")) func = FUNC_SNB_COREI_AVX_2T; + if (feature_available("AVX")) func = FUNC_SNB_COREI_AVX_1T; else{ - fprintf(stderr, "\nError: Function 8 (\"FUNC_SNB_COREI_AVX_2T\") requires AVX, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 8 (\"FUNC_SNB_COREI_AVX_1T\") requires AVX, which is not supported by the processor.\n\n"); } break; case 9: - if (feature_available("AVX")) func = FUNC_SNB_XEONEP_AVX_1T; + if (feature_available("AVX")) func = FUNC_SNB_COREI_AVX_2T; else{ - fprintf(stderr, "\nError: Function 9 (\"FUNC_SNB_XEONEP_AVX_1T\") requires AVX, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 9 (\"FUNC_SNB_COREI_AVX_2T\") requires AVX, which is not supported by the processor.\n\n"); } break; case 10: - if (feature_available("AVX")) func = FUNC_SNB_XEONEP_AVX_2T; + if (feature_available("AVX")) func = FUNC_SNB_XEONEP_AVX_1T; else{ - fprintf(stderr, "\nError: Function 10 (\"FUNC_SNB_XEONEP_AVX_2T\") requires AVX, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 10 (\"FUNC_SNB_XEONEP_AVX_1T\") requires AVX, which is not supported by the processor.\n\n"); } break; case 11: - if (feature_available("SSE2")) func = FUNC_NHM_COREI_SSE2_1T; + if (feature_available("AVX")) func = FUNC_SNB_XEONEP_AVX_2T; else{ - fprintf(stderr, "\nError: Function 11 (\"FUNC_NHM_COREI_SSE2_1T\") requires SSE2, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 11 (\"FUNC_SNB_XEONEP_AVX_2T\") requires AVX, which is not supported by the processor.\n\n"); } break; case 12: - if (feature_available("SSE2")) func = FUNC_NHM_COREI_SSE2_2T; + if (feature_available("SSE2")) func = FUNC_NHM_COREI_SSE2_1T; else{ - fprintf(stderr, "\nError: Function 12 (\"FUNC_NHM_COREI_SSE2_2T\") requires SSE2, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 12 (\"FUNC_NHM_COREI_SSE2_1T\") requires SSE2, which is not supported by the processor.\n\n"); } break; case 13: - if (feature_available("SSE2")) func = FUNC_NHM_XEONEP_SSE2_1T; + if (feature_available("SSE2")) func = FUNC_NHM_COREI_SSE2_2T; else{ - fprintf(stderr, "\nError: Function 13 (\"FUNC_NHM_XEONEP_SSE2_1T\") requires SSE2, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 13 (\"FUNC_NHM_COREI_SSE2_2T\") requires SSE2, which is not supported by the processor.\n\n"); } break; case 14: - if (feature_available("SSE2")) func = FUNC_NHM_XEONEP_SSE2_2T; + if (feature_available("SSE2")) func = FUNC_NHM_XEONEP_SSE2_1T; else{ - fprintf(stderr, "\nError: Function 14 (\"FUNC_NHM_XEONEP_SSE2_2T\") requires SSE2, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 14 (\"FUNC_NHM_XEONEP_SSE2_1T\") requires SSE2, which is not supported by the processor.\n\n"); } break; case 15: + if (feature_available("SSE2")) func = FUNC_NHM_XEONEP_SSE2_2T; + else{ + fprintf(stderr, "\nError: Function 15 (\"FUNC_NHM_XEONEP_SSE2_2T\") requires SSE2, which is not supported by the processor.\n\n"); + } + break; + case 16: if (feature_available("FMA4")) func = FUNC_BLD_OPTERON_FMA4_1T; else{ - fprintf(stderr, "\nError: Function 15 (\"FUNC_BLD_OPTERON_FMA4_1T\") requires FMA4, which is not supported by the processor.\n\n"); + fprintf(stderr, "\nError: Function 16 (\"FUNC_BLD_OPTERON_FMA4_1T\") requires FMA4, which is not supported by the processor.\n\n"); } break; default: @@ -336,10 +375,10 @@ static void evaluate_environment() fprintf(stderr, "\nWarning: not enough CPUs for requested number of threads\n"); } - if (fsbind==NULL) { //use all CPUs if not defined otherwise + if (fsbind==NULL) { // no cpu binding defined #if (defined(linux) || defined(__linux__)) && defined (AFFINITY) CPU_ZERO(&cpuset); - if (NUM_THREADS==0){ + if (NUM_THREADS==0){ // use all CPUs if not defined otherwise for (i = 0; i < cpuinfo->num_cpus; i++) { if (cpu_allowed(i)) { CPU_SET(i, &cpuset); @@ -347,9 +386,26 @@ static void evaluate_environment() } } } - else{ - for (i = 0; i < cpuinfo->num_cpus; i++) { - if (cpu_allowed(i)) CPU_SET(i, &cpuset); + else{ // if -n / --threads is set + int current_cpu=0; + for (i = 0; i < NUM_THREADS; i++) { + /* search for available cpu */ + while(! cpu_allowed(current_cpu) ) { + current_cpu++; + + /* if reached end of avail cpus or max(int) */ + if (current_cpu >= cpuinfo->num_cpus || current_cpu < 0) + { + /* start at beginning */ + fprintf(stderr, "Error: You are requesting more threads than there are CPUs available in the given cpuset.\n"); + fprintf(stderr, "This can be caused by the taskset tool, cgroups, the batch system, or similar mechanisms.\n" ); \ + fprintf(stderr, "Please fix the -n/--threads argument to match the restrictions.\n"); + exit( EACCES ); + } + } + ADD_CPU_SET(current_cpu,cpuset); + /* next cpu for next thread (or one of the following) */ + current_cpu++; } } #ifdef CUDA @@ -365,8 +421,9 @@ static void evaluate_environment() #if (defined(linux) || defined(__linux__)) && defined (AFFINITY) else { // parse CPULIST for binding char *p,*q,*r,*s,*t; - int p_val,r_val,s_val,error=0; + int p_val=0,r_val=0,s_val=0,error=0; + CPU_ZERO(&cpuset); errno=0; p=strdup(fsbind); while(p!=NULL) { @@ -407,19 +464,15 @@ static void evaluate_environment() exit(127); } if ((s)&&(r)) for (i=p_val; (int)i<=r_val; i+=s_val) { - if (cpu_allowed(i)) { - CPU_SET(i,&cpuset); - NUM_THREADS++; - } + ADD_CPU_SET(i,cpuset); + NUM_THREADS++; } else if (r) for (i=p_val; (int)i<=r_val; i++) { - if (cpu_allowed(i)) { - CPU_SET(i,&cpuset); - NUM_THREADS++; - } + ADD_CPU_SET(i,cpuset); + NUM_THREADS++; } - else if (cpu_allowed(p_val)) { - CPU_SET(p_val,&cpuset); + else { + ADD_CPU_SET(p_val,cpuset); NUM_THREADS++; } p=q; @@ -470,6 +523,18 @@ static void evaluate_environment() switch (cpuinfo->family) { case 6: switch (cpuinfo->model) { + case 87: + if (feature_available("AVX512")) { + if (num_threads_per_core() == 4) FUNCTION = FUNC_KNL_XEONPHI_AVX512_4T; + if (FUNCTION == FUNC_NOT_DEFINED) { + fprintf(stderr, "Warning: no code path for %i threads per core!\n",num_threads_per_core()); + } + } + if (FUNCTION == FUNC_NOT_DEFINED) { + fprintf(stderr, "\nWarning: AVX512 is requiered for architecture \"KNL\", but is not supported!\n"); + } + break; + case 78: case 94: if (feature_available("FMA")) { if (num_threads_per_core() == 1) FUNCTION = FUNC_SKL_COREI_FMA_1T; @@ -484,6 +549,8 @@ static void evaluate_environment() break; case 60: case 61: + case 69: + case 70: case 71: if (feature_available("FMA")) { if (num_threads_per_core() == 1) FUNCTION = FUNC_HSW_COREI_FMA_1T; @@ -594,6 +661,22 @@ static void evaluate_environment() } } + /* use AVX512 as fallback if available*/ + if ((FUNCTION == FUNC_NOT_DEFINED)&&(feature_available("AVX512"))) { + /* use function for correct number of threads per core if available */ + if(num_threads_per_core() == 4) { + FUNCTION = FUNC_KNL_XEONPHI_AVX512_4T; + fprintf(stderr, "Warning: using function FUNC_KNL_XEONPHI_AVX512_4T as fallback.\n"); + fprintf(stderr, " You can use the parameter --function to try other functions.\n"); + } + /* use function for 4 threads per core if no function for actual number of thread per core exists*/ + if (FUNCTION == FUNC_NOT_DEFINED) + { + FUNCTION = FUNC_KNL_XEONPHI_AVX512_4T; + fprintf(stderr, "Warning: using function FUNC_KNL_XEONPHI_AVX512_4T as fallback.\n"); + fprintf(stderr, " You can use the parameter --function to try other functions.\n"); + } + } /* use FMA4 as fallback if available*/ if ((FUNCTION == FUNC_NOT_DEFINED)&&(feature_available("FMA4"))) { /* use function for correct number of threads per core if available */ @@ -680,11 +763,28 @@ static void evaluate_environment() switch (FUNCTION) { + case FUNC_KNL_XEONPHI_AVX512_4T: + if (verbose) printf("\n Taking AVX512 Path optimized for Knights_Landing - 4 thread(s) per core"); + + + + + BUFFERSIZE[0] = 8192; + BUFFERSIZE[1] = 131072; + BUFFERSIZE[2] = 0; + RAMBUFFERSIZE = 6553600; + if (verbose) { + printf("\n Used buffersizes per thread:\n"); + for (i = 0; i < cpuinfo->Cachelevels; i++) printf(" - L%d-Cache: %d Bytes\n", i + 1, BUFFERSIZE[i]); + printf(" - Memory: %llu Bytes\n\n", RAMBUFFERSIZE); + } + break; case FUNC_SKL_COREI_FMA_1T: if (verbose) printf("\n Taking FMA Path optimized for Skylake - 1 thread(s) per core"); + BUFFERSIZE[0] = 32768; BUFFERSIZE[1] = 262144; BUFFERSIZE[2] = 1572864; @@ -700,6 +800,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 16384; BUFFERSIZE[1] = 131072; BUFFERSIZE[2] = 786432; @@ -715,6 +816,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 32768; BUFFERSIZE[1] = 262144; BUFFERSIZE[2] = 1572864; @@ -730,6 +832,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 16384; BUFFERSIZE[1] = 131072; BUFFERSIZE[2] = 786432; @@ -745,6 +848,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 32768; BUFFERSIZE[1] = 262144; BUFFERSIZE[2] = 2621440; @@ -760,6 +864,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 16384; BUFFERSIZE[1] = 131072; BUFFERSIZE[2] = 1310720; @@ -775,6 +880,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 32768; BUFFERSIZE[1] = 262144; BUFFERSIZE[2] = 1572864; @@ -790,6 +896,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 16384; BUFFERSIZE[1] = 131072; BUFFERSIZE[2] = 786432; @@ -805,6 +912,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 32768; BUFFERSIZE[1] = 262144; BUFFERSIZE[2] = 2621440; @@ -820,6 +928,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 16384; BUFFERSIZE[1] = 131072; BUFFERSIZE[2] = 1310720; @@ -835,6 +944,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 32768; BUFFERSIZE[1] = 262144; BUFFERSIZE[2] = 1572864; @@ -850,6 +960,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 16384; BUFFERSIZE[1] = 131072; BUFFERSIZE[2] = 786432; @@ -865,6 +976,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 32768; BUFFERSIZE[1] = 262144; BUFFERSIZE[2] = 2097152; @@ -880,6 +992,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 16384; BUFFERSIZE[1] = 131072; BUFFERSIZE[2] = 1048576; @@ -895,6 +1008,7 @@ static void evaluate_environment() + BUFFERSIZE[0] = 16384; BUFFERSIZE[1] = 1048576; BUFFERSIZE[2] = 786432; @@ -916,6 +1030,8 @@ static void evaluate_environment() int main(int argc, char *argv[]) { int i,c; + unsigned long long iterations=0; + #ifdef CUDA gpustruct * structpointer=malloc(sizeof(gpustruct)); structpointer->useDouble=1; //we want to use Doubles, if no -f Argument is given @@ -930,6 +1046,7 @@ int main(int argc, char *argv[]) {"version", no_argument, 0, 'v'}, {"warranty", no_argument, 0, 'w'}, {"quiet", no_argument, 0, 'q'}, + {"report", no_argument, 0, 'r'}, {"avail", no_argument, 0, 'a'}, {"function", required_argument, 0, 'i'}, #ifdef CUDA @@ -952,9 +1069,9 @@ int main(int argc, char *argv[]) { #if (defined(linux) || defined(__linux__)) && defined (AFFINITY) - c = getopt_long(argc, argv, "chvwqafb:i:t:l:p:n:m:g:", long_options, NULL); + c = getopt_long(argc, argv, "chvwqarfb:i:t:l:p:n:m:g:", long_options, NULL); #else - c = getopt_long(argc, argv, "chvwqafi:t:l:p:n:m:g:", long_options, NULL); + c = getopt_long(argc, argv, "chvwqarfi:t:l:p:n:m:g:", long_options, NULL); #endif if(c == -1) break; @@ -980,6 +1097,9 @@ int main(int argc, char *argv[]) FUNCTION=get_function((unsigned int)strtol(optarg,NULL,10)); if (FUNCTION==FUNC_UNKNOWN) return EXIT_FAILURE; break; + case 'r': + if (verbose) verbose = 2; + break; case 'q': #ifdef CUDA structpointer->verbose=0; @@ -987,10 +1107,18 @@ int main(int argc, char *argv[]) verbose = 0; break; case 'n': + if (fsbind!=NULL){ + printf("Error: -b/--bind and -n/--threads cannot be used together\n"); + return EXIT_FAILURE; + } NUM_THREADS=(unsigned int)strtol(optarg,NULL,10); break; #if (defined(linux) || defined(__linux__)) && defined (AFFINITY) case 'b': + if (NUM_THREADS){ + printf("Error: -b/--bind and -n/--threads cannot be used together\n"); + return EXIT_FAILURE; + } fsbind=strdup(optarg); break; #endif @@ -1082,6 +1210,30 @@ int main(int argc, char *argv[]) /* wait for threads after watchdog has requested termination */ for(i = 0; i < mdp->num_threads; i++) pthread_join(threads[i], NULL); + if (verbose == 2){ + unsigned long long start_tsc,stop_tsc; + double runtime; + + printf("\nperformance report:\n"); + + start_tsc=mdp->threaddata[0].start_tsc; + stop_tsc=mdp->threaddata[0].stop_tsc; + for(i = 0; i < mdp->num_threads; i++){ + printf("Thread %i: %llu iterations, tsc_delta: %llu\n",i,mdp->threaddata[i].iterations, mdp->threaddata[i].stop_tsc - mdp->threaddata[i].start_tsc ); + iterations+=mdp->threaddata[i].iterations; + if (start_tsc > mdp->threaddata[i].start_tsc) start_tsc = mdp->threaddata[i].start_tsc; + if (stop_tsc < mdp->threaddata[i].stop_tsc) stop_tsc = mdp->threaddata[i].stop_tsc; + } + printf("\ntotal iterations: %llu\n",iterations); + runtime=(double)(stop_tsc - start_tsc) / (double)cpuinfo->clockrate; + printf("runtime: %.2f seconds (%llu cycles)\n\n",runtime, stop_tsc - start_tsc); + + printf("estimated floating point performance: %.2f GFLOPS\n", (double)mdp->threaddata[0].flops*0.000000001*(double)iterations/runtime); + printf("estimated memory bandwidth: %.2f GB/s\n", (double)mdp->threaddata[0].bytes*0.000000001*(double)iterations/runtime); + + printf("\n"); + } + #ifdef CUDA free(structpointer); #endif diff --git a/sse2_functions.c b/sse2_functions.c index fd1abdec..f53d1030 100644 --- a/sse2_functions.c +++ b/sse2_functions.c @@ -23,12 +23,33 @@ - int init_nhm_corei_sse2_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_nhm_corei_sse2_1t(unsigned long long addrMem) + + int init_nhm_corei_sse2_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_nhm_corei_sse2_1t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i = 0; i<13340672; i++) *((double*)(addrMem + 8*i)) = i * 1.654738925401e-15; + // lines with register operations + threaddata->flops+=2*2; // 1 128 bit operation + + // lines with L1 operations + threaddata->flops+=70*2; // 1 128 bit operation + + // lines with L2 operations + threaddata->flops+=0*2; // 1 128 bit operation + + // lines with L3 operations + threaddata->flops+=0*2; // 1 128 bit operation + + // lines with RAM operations + threaddata->flops+=1*2; // 1 128 bit operation + threaddata->bytes=1*64; // 1 memory access + + threaddata->flops*=21; + threaddata->bytes*=21; + return EXIT_SUCCESS; } @@ -39,10 +60,10 @@ int init_nhm_corei_sse2_1t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_nhm_corei_sse2_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_nhm_corei_sse2_1t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_nhm_corei_sse2_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_nhm_corei_sse2_1t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -57,11 +78,13 @@ int asm_work_nhm_corei_sse2_1t(unsigned long long addrMem, unsigned long long ad * - r11: temp register for initialization of SIMD-registers * - r12: stores cacheline width as increment for buffer addresses * - r13: stores address of shared variable that controls load level + * - r14: stores iteration counter * - mm*,xmm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r13;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r13;" // store address of shared variable that controls load level + "mov %%rcx, %%r14;" // store iteration counter "mov $64, %%r12;" // increment after each cache/memory access //Initialize SSE-Registers for Addition "movapd 0(%%rax), %%xmm0;" @@ -1640,25 +1663,47 @@ int asm_work_nhm_corei_sse2_1t(unsigned long long addrMem, unsigned long long ad "mov %%rax, %%rdi;" "add $1572864, %%rdi;" "_work_no_ram_reset_nhm_corei_sse2_1t:" + "inc %%r14;" // increment iteration counter "mov %%rax, %%rbx;" - "mov (%%r13), %%r11;" - "test $1, %%r11;" + "testq $1, (%%r13);" "jnz _work_loop_nhm_corei_sse2_1t;" - : - : "r"(addrMem), "r"(addrHigh) - : "%rax", "%rbx", "%rcx", "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%r14, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } - int init_nhm_corei_sse2_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_nhm_corei_sse2_2t(unsigned long long addrMem) + + int init_nhm_corei_sse2_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_nhm_corei_sse2_2t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i = 0; i<6670336; i++) *((double*)(addrMem + 8*i)) = i * 1.654738925401e-15; + // lines with register operations + threaddata->flops+=2*2; // 1 128 bit operation + + // lines with L1 operations + threaddata->flops+=70*2; // 1 128 bit operation + + // lines with L2 operations + threaddata->flops+=0*2; // 1 128 bit operation + + // lines with L3 operations + threaddata->flops+=0*2; // 1 128 bit operation + + // lines with RAM operations + threaddata->flops+=1*2; // 1 128 bit operation + threaddata->bytes=1*64; // 1 memory access + + threaddata->flops*=10; + threaddata->bytes*=10; + return EXIT_SUCCESS; } @@ -1669,10 +1714,10 @@ int init_nhm_corei_sse2_2t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_nhm_corei_sse2_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_nhm_corei_sse2_2t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_nhm_corei_sse2_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_nhm_corei_sse2_2t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -1687,11 +1732,13 @@ int asm_work_nhm_corei_sse2_2t(unsigned long long addrMem, unsigned long long ad * - r11: temp register for initialization of SIMD-registers * - r12: stores cacheline width as increment for buffer addresses * - r13: stores address of shared variable that controls load level + * - r14: stores iteration counter * - mm*,xmm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r13;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r13;" // store address of shared variable that controls load level + "mov %%rcx, %%r14;" // store iteration counter "mov $64, %%r12;" // increment after each cache/memory access //Initialize SSE-Registers for Addition "movapd 0(%%rax), %%xmm0;" @@ -2467,25 +2514,47 @@ int asm_work_nhm_corei_sse2_2t(unsigned long long addrMem, unsigned long long ad "mov %%rax, %%rdi;" "add $786432, %%rdi;" "_work_no_ram_reset_nhm_corei_sse2_2t:" + "inc %%r14;" // increment iteration counter "mov %%rax, %%rbx;" - "mov (%%r13), %%r11;" - "test $1, %%r11;" + "testq $1, (%%r13);" "jnz _work_loop_nhm_corei_sse2_2t;" - : - : "r"(addrMem), "r"(addrHigh) - : "%rax", "%rbx", "%rcx", "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%r14, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } - int init_nhm_xeonep_sse2_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_nhm_xeonep_sse2_1t(unsigned long long addrMem) + + int init_nhm_xeonep_sse2_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_nhm_xeonep_sse2_1t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i = 0; i<13406208; i++) *((double*)(addrMem + 8*i)) = i * 1.654738925401e-15; + // lines with register operations + threaddata->flops+=2*2; // 1 128 bit operation + + // lines with L1 operations + threaddata->flops+=60*2; // 1 128 bit operation + + // lines with L2 operations + threaddata->flops+=0*2; // 1 128 bit operation + + // lines with L3 operations + threaddata->flops+=0*2; // 1 128 bit operation + + // lines with RAM operations + threaddata->flops+=1*2; // 1 128 bit operation + threaddata->bytes=1*64; // 1 memory access + + threaddata->flops*=24; + threaddata->bytes*=24; + return EXIT_SUCCESS; } @@ -2496,10 +2565,10 @@ int init_nhm_xeonep_sse2_1t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_nhm_xeonep_sse2_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_nhm_xeonep_sse2_1t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_nhm_xeonep_sse2_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_nhm_xeonep_sse2_1t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -2514,11 +2583,13 @@ int asm_work_nhm_xeonep_sse2_1t(unsigned long long addrMem, unsigned long long a * - r11: temp register for initialization of SIMD-registers * - r12: stores cacheline width as increment for buffer addresses * - r13: stores address of shared variable that controls load level + * - r14: stores iteration counter * - mm*,xmm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r13;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r13;" // store address of shared variable that controls load level + "mov %%rcx, %%r14;" // store iteration counter "mov $64, %%r12;" // increment after each cache/memory access //Initialize SSE-Registers for Addition "movapd 0(%%rax), %%xmm0;" @@ -4076,25 +4147,47 @@ int asm_work_nhm_xeonep_sse2_1t(unsigned long long addrMem, unsigned long long a "mov %%rax, %%rdi;" "add $2097152, %%rdi;" "_work_no_ram_reset_nhm_xeonep_sse2_1t:" + "inc %%r14;" // increment iteration counter "mov %%rax, %%rbx;" - "mov (%%r13), %%r11;" - "test $1, %%r11;" + "testq $1, (%%r13);" "jnz _work_loop_nhm_xeonep_sse2_1t;" - : - : "r"(addrMem), "r"(addrHigh) - : "%rax", "%rbx", "%rcx", "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%r14, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } - int init_nhm_xeonep_sse2_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_nhm_xeonep_sse2_2t(unsigned long long addrMem) + + int init_nhm_xeonep_sse2_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_nhm_xeonep_sse2_2t(threaddata_t* threaddata) { + unsigned long long addrMem = threaddata->addrMem; int i; for (i = 0; i<6703104; i++) *((double*)(addrMem + 8*i)) = i * 1.654738925401e-15; + // lines with register operations + threaddata->flops+=2*2; // 1 128 bit operation + + // lines with L1 operations + threaddata->flops+=60*2; // 1 128 bit operation + + // lines with L2 operations + threaddata->flops+=0*2; // 1 128 bit operation + + // lines with L3 operations + threaddata->flops+=0*2; // 1 128 bit operation + + // lines with RAM operations + threaddata->flops+=1*2; // 1 128 bit operation + threaddata->bytes=1*64; // 1 memory access + + threaddata->flops*=12; + threaddata->bytes*=12; + return EXIT_SUCCESS; } @@ -4105,10 +4198,10 @@ int init_nhm_xeonep_sse2_2t(unsigned long long addrMem) * @input - addrMem: pointer to buffer * @return EXIT_SUCCESS */ -int asm_work_nhm_xeonep_sse2_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_nhm_xeonep_sse2_2t(unsigned long long addrMem, unsigned long long addrHigh) +int asm_work_nhm_xeonep_sse2_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_nhm_xeonep_sse2_2t(threaddata_t* threaddata) { - if (*((unsigned long long*)addrHigh) == 0) return EXIT_SUCCESS; + if (*((unsigned long long*)threaddata->addrHigh) == 0) return EXIT_SUCCESS; /* input: * - addrMem -> rax * register usage: @@ -4123,11 +4216,13 @@ int asm_work_nhm_xeonep_sse2_2t(unsigned long long addrMem, unsigned long long a * - r11: temp register for initialization of SIMD-registers * - r12: stores cacheline width as increment for buffer addresses * - r13: stores address of shared variable that controls load level + * - r14: stores iteration counter * - mm*,xmm*: data registers for SIMD instructions */ __asm__ __volatile__( - "mov %0, %%rax;" // store start address of buffer - "mov %1, %%r13;" // store address of shared variable that controls load level + "mov %%rax, %%rax;" // store start address of buffer + "mov %%rbx, %%r13;" // store address of shared variable that controls load level + "mov %%rcx, %%r14;" // store iteration counter "mov $64, %%r12;" // increment after each cache/memory access //Initialize SSE-Registers for Addition "movapd 0(%%rax), %%xmm0;" @@ -4929,13 +5024,14 @@ int asm_work_nhm_xeonep_sse2_2t(unsigned long long addrMem, unsigned long long a "mov %%rax, %%rdi;" "add $1048576, %%rdi;" "_work_no_ram_reset_nhm_xeonep_sse2_2t:" + "inc %%r14;" // increment iteration counter "mov %%rax, %%rbx;" - "mov (%%r13), %%r11;" - "test $1, %%r11;" + "testq $1, (%%r13);" "jnz _work_loop_nhm_xeonep_sse2_2t;" - : - : "r"(addrMem), "r"(addrHigh) - : "%rax", "%rbx", "%rcx", "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + "movq %%r14, %%rax;" // restore iteration counter + : "=a" (threaddata->iterations) + : "a"(threaddata->addrMem), "b"(threaddata->addrHigh), "c" (threaddata->iterations) + : "%rdx", "%rdi", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" ); return EXIT_SUCCESS; } diff --git a/work.c b/work.c index e2dd94cd..5528bfc8 100644 --- a/work.c +++ b/work.c @@ -123,50 +123,53 @@ void *thread(void *threaddata) /* call init function */ switch (mydata->FUNCTION) { + case FUNC_KNL_XEONPHI_AVX512_4T: + tmp = init_knl_xeonphi_avx512_4t(mydata); + break; case FUNC_SKL_COREI_FMA_1T: - tmp = init_skl_corei_fma_1t(mydata->addrMem); + tmp = init_skl_corei_fma_1t(mydata); break; case FUNC_SKL_COREI_FMA_2T: - tmp = init_skl_corei_fma_2t(mydata->addrMem); + tmp = init_skl_corei_fma_2t(mydata); break; case FUNC_HSW_COREI_FMA_1T: - tmp = init_hsw_corei_fma_1t(mydata->addrMem); + tmp = init_hsw_corei_fma_1t(mydata); break; case FUNC_HSW_COREI_FMA_2T: - tmp = init_hsw_corei_fma_2t(mydata->addrMem); + tmp = init_hsw_corei_fma_2t(mydata); break; case FUNC_HSW_XEONEP_FMA_1T: - tmp = init_hsw_xeonep_fma_1t(mydata->addrMem); + tmp = init_hsw_xeonep_fma_1t(mydata); break; case FUNC_HSW_XEONEP_FMA_2T: - tmp = init_hsw_xeonep_fma_2t(mydata->addrMem); + tmp = init_hsw_xeonep_fma_2t(mydata); break; case FUNC_SNB_COREI_AVX_1T: - tmp = init_snb_corei_avx_1t(mydata->addrMem); + tmp = init_snb_corei_avx_1t(mydata); break; case FUNC_SNB_COREI_AVX_2T: - tmp = init_snb_corei_avx_2t(mydata->addrMem); + tmp = init_snb_corei_avx_2t(mydata); break; case FUNC_SNB_XEONEP_AVX_1T: - tmp = init_snb_xeonep_avx_1t(mydata->addrMem); + tmp = init_snb_xeonep_avx_1t(mydata); break; case FUNC_SNB_XEONEP_AVX_2T: - tmp = init_snb_xeonep_avx_2t(mydata->addrMem); + tmp = init_snb_xeonep_avx_2t(mydata); break; case FUNC_NHM_COREI_SSE2_1T: - tmp = init_nhm_corei_sse2_1t(mydata->addrMem); + tmp = init_nhm_corei_sse2_1t(mydata); break; case FUNC_NHM_COREI_SSE2_2T: - tmp = init_nhm_corei_sse2_2t(mydata->addrMem); + tmp = init_nhm_corei_sse2_2t(mydata); break; case FUNC_NHM_XEONEP_SSE2_1T: - tmp = init_nhm_xeonep_sse2_1t(mydata->addrMem); + tmp = init_nhm_xeonep_sse2_1t(mydata); break; case FUNC_NHM_XEONEP_SSE2_2T: - tmp = init_nhm_xeonep_sse2_2t(mydata->addrMem); + tmp = init_nhm_xeonep_sse2_2t(mydata); break; case FUNC_BLD_OPTERON_FMA4_1T: - tmp = init_bld_opteron_fma4_1t(mydata->addrMem); + tmp = init_bld_opteron_fma4_1t(mydata); break; default: fprintf(stderr, "Error: unknown function %i\n", mydata->FUNCTION); @@ -188,6 +191,9 @@ void *thread(void *threaddata) old = THREAD_WORK; global_data->ack = id + 1; + /* record thread's start timestamp */ + ((threaddata_t *)threaddata)->start_tsc = timestamp(); + /* will be terminated by watchdog * watchdog also alters mydata->addrHigh to switch between high and low load function */ @@ -201,50 +207,53 @@ void *thread(void *threaddata) #endif switch (mydata->FUNCTION) { + case FUNC_KNL_XEONPHI_AVX512_4T: + tmp=asm_work_knl_xeonphi_avx512_4t(mydata); + break; case FUNC_SKL_COREI_FMA_1T: - tmp=asm_work_skl_corei_fma_1t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_skl_corei_fma_1t(mydata); break; case FUNC_SKL_COREI_FMA_2T: - tmp=asm_work_skl_corei_fma_2t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_skl_corei_fma_2t(mydata); break; case FUNC_HSW_COREI_FMA_1T: - tmp=asm_work_hsw_corei_fma_1t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_hsw_corei_fma_1t(mydata); break; case FUNC_HSW_COREI_FMA_2T: - tmp=asm_work_hsw_corei_fma_2t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_hsw_corei_fma_2t(mydata); break; case FUNC_HSW_XEONEP_FMA_1T: - tmp=asm_work_hsw_xeonep_fma_1t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_hsw_xeonep_fma_1t(mydata); break; case FUNC_HSW_XEONEP_FMA_2T: - tmp=asm_work_hsw_xeonep_fma_2t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_hsw_xeonep_fma_2t(mydata); break; case FUNC_SNB_COREI_AVX_1T: - tmp=asm_work_snb_corei_avx_1t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_snb_corei_avx_1t(mydata); break; case FUNC_SNB_COREI_AVX_2T: - tmp=asm_work_snb_corei_avx_2t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_snb_corei_avx_2t(mydata); break; case FUNC_SNB_XEONEP_AVX_1T: - tmp=asm_work_snb_xeonep_avx_1t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_snb_xeonep_avx_1t(mydata); break; case FUNC_SNB_XEONEP_AVX_2T: - tmp=asm_work_snb_xeonep_avx_2t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_snb_xeonep_avx_2t(mydata); break; case FUNC_NHM_COREI_SSE2_1T: - tmp=asm_work_nhm_corei_sse2_1t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_nhm_corei_sse2_1t(mydata); break; case FUNC_NHM_COREI_SSE2_2T: - tmp=asm_work_nhm_corei_sse2_2t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_nhm_corei_sse2_2t(mydata); break; case FUNC_NHM_XEONEP_SSE2_1T: - tmp=asm_work_nhm_xeonep_sse2_1t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_nhm_xeonep_sse2_1t(mydata); break; case FUNC_NHM_XEONEP_SSE2_2T: - tmp=asm_work_nhm_xeonep_sse2_2t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_nhm_xeonep_sse2_2t(mydata); break; case FUNC_BLD_OPTERON_FMA4_1T: - tmp=asm_work_bld_opteron_fma4_1t(mydata->addrMem,mydata->addrHigh); + tmp=asm_work_bld_opteron_fma4_1t(mydata); break; default: fprintf(stderr,"Error: unknown function %i\n",mydata->FUNCTION); @@ -274,6 +283,8 @@ void *thread(void *threaddata) /* terminate if master signals end of run */ if(*((volatile unsigned long long *)(mydata->addrHigh)) == LOAD_STOP) { + ((threaddata_t *)threaddata) -> stop_tsc = timestamp(); + pthread_exit(NULL); } } // end while diff --git a/work.h b/work.h index 9fd3f4a6..a3908d24 100644 --- a/work.h +++ b/work.h @@ -25,21 +25,22 @@ #include "firestarter_global.h" #include -#define FUNC_SKL_COREI_FMA_1T 1 -#define FUNC_SKL_COREI_FMA_2T 2 -#define FUNC_HSW_COREI_FMA_1T 3 -#define FUNC_HSW_COREI_FMA_2T 4 -#define FUNC_HSW_XEONEP_FMA_1T 5 -#define FUNC_HSW_XEONEP_FMA_2T 6 -#define FUNC_SNB_COREI_AVX_1T 7 -#define FUNC_SNB_COREI_AVX_2T 8 -#define FUNC_SNB_XEONEP_AVX_1T 9 -#define FUNC_SNB_XEONEP_AVX_2T 10 -#define FUNC_NHM_COREI_SSE2_1T 11 -#define FUNC_NHM_COREI_SSE2_2T 12 -#define FUNC_NHM_XEONEP_SSE2_1T 13 -#define FUNC_NHM_XEONEP_SSE2_2T 14 -#define FUNC_BLD_OPTERON_FMA4_1T 15 +#define FUNC_KNL_XEONPHI_AVX512_4T 1 +#define FUNC_SKL_COREI_FMA_1T 2 +#define FUNC_SKL_COREI_FMA_2T 3 +#define FUNC_HSW_COREI_FMA_1T 4 +#define FUNC_HSW_COREI_FMA_2T 5 +#define FUNC_HSW_XEONEP_FMA_1T 6 +#define FUNC_HSW_XEONEP_FMA_2T 7 +#define FUNC_SNB_COREI_AVX_1T 8 +#define FUNC_SNB_COREI_AVX_2T 9 +#define FUNC_SNB_XEONEP_AVX_1T 10 +#define FUNC_SNB_XEONEP_AVX_2T 11 +#define FUNC_NHM_COREI_SSE2_1T 12 +#define FUNC_NHM_COREI_SSE2_2T 13 +#define FUNC_NHM_XEONEP_SSE2_1T 14 +#define FUNC_NHM_XEONEP_SSE2_2T 15 +#define FUNC_BLD_OPTERON_FMA4_1T 16 /* @@ -55,99 +56,105 @@ extern void *thread(void *threaddata); /* * init functions */ -int init_skl_corei_fma_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_skl_corei_fma_1t(unsigned long long addrMem); +int init_knl_xeonphi_avx512_4t(threaddata_t* threaddata) __attribute__((noinline)); +int init_knl_xeonphi_avx512_4t(threaddata_t* threaddata); -int init_skl_corei_fma_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_skl_corei_fma_2t(unsigned long long addrMem); +int init_skl_corei_fma_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_skl_corei_fma_1t(threaddata_t* threaddata); -int init_hsw_corei_fma_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_hsw_corei_fma_1t(unsigned long long addrMem); +int init_skl_corei_fma_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_skl_corei_fma_2t(threaddata_t* threaddata); -int init_hsw_corei_fma_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_hsw_corei_fma_2t(unsigned long long addrMem); +int init_hsw_corei_fma_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_hsw_corei_fma_1t(threaddata_t* threaddata); -int init_hsw_xeonep_fma_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_hsw_xeonep_fma_1t(unsigned long long addrMem); +int init_hsw_corei_fma_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_hsw_corei_fma_2t(threaddata_t* threaddata); -int init_hsw_xeonep_fma_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_hsw_xeonep_fma_2t(unsigned long long addrMem); +int init_hsw_xeonep_fma_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_hsw_xeonep_fma_1t(threaddata_t* threaddata); -int init_snb_corei_avx_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_snb_corei_avx_1t(unsigned long long addrMem); +int init_hsw_xeonep_fma_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_hsw_xeonep_fma_2t(threaddata_t* threaddata); -int init_snb_corei_avx_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_snb_corei_avx_2t(unsigned long long addrMem); +int init_snb_corei_avx_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_snb_corei_avx_1t(threaddata_t* threaddata); -int init_snb_xeonep_avx_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_snb_xeonep_avx_1t(unsigned long long addrMem); +int init_snb_corei_avx_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_snb_corei_avx_2t(threaddata_t* threaddata); -int init_snb_xeonep_avx_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_snb_xeonep_avx_2t(unsigned long long addrMem); +int init_snb_xeonep_avx_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_snb_xeonep_avx_1t(threaddata_t* threaddata); -int init_nhm_corei_sse2_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_nhm_corei_sse2_1t(unsigned long long addrMem); +int init_snb_xeonep_avx_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_snb_xeonep_avx_2t(threaddata_t* threaddata); -int init_nhm_corei_sse2_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_nhm_corei_sse2_2t(unsigned long long addrMem); +int init_nhm_corei_sse2_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_nhm_corei_sse2_1t(threaddata_t* threaddata); -int init_nhm_xeonep_sse2_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_nhm_xeonep_sse2_1t(unsigned long long addrMem); +int init_nhm_corei_sse2_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_nhm_corei_sse2_2t(threaddata_t* threaddata); -int init_nhm_xeonep_sse2_2t(unsigned long long addrMem) __attribute__((noinline)); -int init_nhm_xeonep_sse2_2t(unsigned long long addrMem); +int init_nhm_xeonep_sse2_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_nhm_xeonep_sse2_1t(threaddata_t* threaddata); -int init_bld_opteron_fma4_1t(unsigned long long addrMem) __attribute__((noinline)); -int init_bld_opteron_fma4_1t(unsigned long long addrMem); +int init_nhm_xeonep_sse2_2t(threaddata_t* threaddata) __attribute__((noinline)); +int init_nhm_xeonep_sse2_2t(threaddata_t* threaddata); + +int init_bld_opteron_fma4_1t(threaddata_t* threaddata) __attribute__((noinline)); +int init_bld_opteron_fma4_1t(threaddata_t* threaddata); /* * stress test functions */ -int asm_work_skl_corei_fma_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_skl_corei_fma_1t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_knl_xeonphi_avx512_4t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_knl_xeonphi_avx512_4t(threaddata_t* threaddata); + +int asm_work_skl_corei_fma_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_skl_corei_fma_1t(threaddata_t* threaddata); -int asm_work_skl_corei_fma_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_skl_corei_fma_2t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_skl_corei_fma_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_skl_corei_fma_2t(threaddata_t* threaddata); -int asm_work_hsw_corei_fma_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_hsw_corei_fma_1t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_hsw_corei_fma_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_hsw_corei_fma_1t(threaddata_t* threaddata); -int asm_work_hsw_corei_fma_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_hsw_corei_fma_2t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_hsw_corei_fma_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_hsw_corei_fma_2t(threaddata_t* threaddata); -int asm_work_hsw_xeonep_fma_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_hsw_xeonep_fma_1t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_hsw_xeonep_fma_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_hsw_xeonep_fma_1t(threaddata_t* threaddata); -int asm_work_hsw_xeonep_fma_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_hsw_xeonep_fma_2t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_hsw_xeonep_fma_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_hsw_xeonep_fma_2t(threaddata_t* threaddata); -int asm_work_snb_corei_avx_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_snb_corei_avx_1t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_snb_corei_avx_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_snb_corei_avx_1t(threaddata_t* threaddata); -int asm_work_snb_corei_avx_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_snb_corei_avx_2t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_snb_corei_avx_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_snb_corei_avx_2t(threaddata_t* threaddata); -int asm_work_snb_xeonep_avx_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_snb_xeonep_avx_1t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_snb_xeonep_avx_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_snb_xeonep_avx_1t(threaddata_t* threaddata); -int asm_work_snb_xeonep_avx_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_snb_xeonep_avx_2t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_snb_xeonep_avx_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_snb_xeonep_avx_2t(threaddata_t* threaddata); -int asm_work_nhm_corei_sse2_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_nhm_corei_sse2_1t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_nhm_corei_sse2_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_nhm_corei_sse2_1t(threaddata_t* threaddata); -int asm_work_nhm_corei_sse2_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_nhm_corei_sse2_2t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_nhm_corei_sse2_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_nhm_corei_sse2_2t(threaddata_t* threaddata); -int asm_work_nhm_xeonep_sse2_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_nhm_xeonep_sse2_1t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_nhm_xeonep_sse2_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_nhm_xeonep_sse2_1t(threaddata_t* threaddata); -int asm_work_nhm_xeonep_sse2_2t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_nhm_xeonep_sse2_2t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_nhm_xeonep_sse2_2t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_nhm_xeonep_sse2_2t(threaddata_t* threaddata); -int asm_work_bld_opteron_fma4_1t(unsigned long long addrMem, unsigned long long addrHigh) __attribute__((noinline)); -int asm_work_bld_opteron_fma4_1t(unsigned long long addrMem, unsigned long long addrHigh); +int asm_work_bld_opteron_fma4_1t(threaddata_t* threaddata) __attribute__((noinline)); +int asm_work_bld_opteron_fma4_1t(threaddata_t* threaddata); /* diff --git a/x86.c b/x86.c index b231214f..fc765bcc 100644 --- a/x86.c +++ b/x86.c @@ -53,9 +53,6 @@ static int has_invariant_rdtsc(); #endif #endif -/** used to store Registers {R|E}AX, {R|E}BX, {R|E}CX and {R|E}DX */ -static unsigned long long a,b,c,d; - /* * declarations of x86 specific functions, only used within this file */ @@ -77,11 +74,11 @@ static int has_htt(); /** 64 Bit implementations */ #if defined _64_BIT -static unsigned long long reg_a,reg_b,reg_c,reg_d; - static void cpuid(unsigned long long *a, unsigned long long *b, unsigned long long *c, unsigned long long *d) { + unsigned long long reg_a,reg_b,reg_c,reg_d; + __asm__ __volatile__( "cpuid;" : "=a" (reg_a), "=b" (reg_b), "=c" (reg_c), "=d" (reg_d) @@ -101,6 +98,8 @@ static int has_cpuid() unsigned long long timestamp() { + unsigned long long reg_a,reg_d; + if (!has_rdtsc()) return 0; __asm__ __volatile__("rdtsc;": "=a" (reg_a), "=d" (reg_d)); return (reg_d<<32)|(reg_a&0xffffffffULL); @@ -110,11 +109,11 @@ unsigned long long timestamp() /** 32 Bit implementations */ #if defined(_32_BIT) -/* 32 Bit Registers */ -static unsigned int reg_a,reg_b,reg_c,reg_d; static void cpuid(unsigned long long *a, unsigned long long *b, unsigned long long *c, unsigned long long *d) { + unsigned int reg_a,reg_b,reg_c,reg_d; + __asm__ __volatile__( "cpuid;" : "=a" (reg_a), "=b" (reg_b), "=c" (reg_c), "=d" (reg_d) @@ -165,6 +164,8 @@ static int has_cpuid() unsigned long long timestamp() { + unsigned int reg_a,reg_d; + if (!has_rdtsc()) return 0; __asm__ __volatile__("rdtsc;": "=a" (reg_a) , "=d" (reg_d)); // upper 32 Bit in EDX, lower 32 Bit in EAX @@ -206,6 +207,8 @@ void get_architecture(char* arch, size_t len) int has_rdtsc() { + unsigned long long a,b,c,d; + if (!has_cpuid()) return 0; a=0; @@ -223,6 +226,7 @@ int has_rdtsc() int has_invariant_rdtsc() { + unsigned long long a,b,c,d; char tmp[_HW_DETECT_MAX_OUTPUT]; int res=0; @@ -281,6 +285,8 @@ int has_invariant_rdtsc() static int has_htt() { + unsigned long long a,b,c,d; + if (!has_cpuid()) return 0; a=0; cpuid(&a,&b,&c,&d); @@ -295,6 +301,7 @@ static int has_htt() int get_cpu_vendor(char* vendor, size_t len) { + unsigned long long a,b,c,d; char tmp_vendor[13]; if (!has_cpuid()) return generic_get_cpu_vendor(vendor); @@ -312,6 +319,7 @@ int get_cpu_vendor(char* vendor, size_t len) int get_cpu_name(char* name, size_t len) { + unsigned long long a,b,c,d; char tmp[48]; char* start; @@ -361,6 +369,8 @@ int get_cpu_name(char* name, size_t len) int get_cpu_family() { + unsigned long long a,b,c,d; + if (!has_cpuid()) return generic_get_cpu_family(); a=0; cpuid(&a,&b,&c,&d); @@ -375,6 +385,8 @@ int get_cpu_family() } int get_cpu_model() { + unsigned long long a,b,c,d; + if (!has_cpuid()) return generic_get_cpu_model(); a=0; cpuid(&a,&b,&c,&d); @@ -389,6 +401,8 @@ int get_cpu_model() } int get_cpu_stepping() { + unsigned long long a,b,c,d; + if (!has_cpuid()) return generic_get_cpu_stepping(); a=0; cpuid(&a,&b,&c,&d); @@ -404,6 +418,7 @@ int get_cpu_stepping() int get_cpu_isa_extensions(char* features, size_t len) { + unsigned long long a,b,c,d; unsigned long long max,max_ext; char tmp[16]; @@ -451,6 +466,14 @@ int get_cpu_isa_extensions(char* features, size_t len) if (c&(1<<23)) strncat(features,"POPCNT ",(len-strlen(features))-1); } + if (max>=7) + { + a=7;c=0; + cpuid(&a,&b,&c,&d); + + if (b&(1<<5)) strncat(features,"AVX2 ", (len-strlen(features))-1); + if (b&(1<<16)) strncat(features,"AVX512 ", (len-strlen(features))-1); + } if (max_ext>=0x80000001) { a=0x80000001; @@ -591,6 +614,7 @@ unsigned long long get_cpu_clockrate(int check,int cpu) */ int num_caches(int cpu) { + unsigned long long a,b,c,d; unsigned long long max,max_ext; char tmp[16]; int num; @@ -660,6 +684,7 @@ int num_caches(int cpu) //TODO use sysfs if available to determine cache sharing int cache_info(int cpu,int id, char* output, size_t len) { + unsigned long long a,b,c,d; unsigned long long max,max_ext; char tmp[16]; @@ -1120,6 +1145,7 @@ int num_packages() int num_cores_per_package() { + unsigned long long a,b,c,d; char tmp[16]; int num=-1; @@ -1167,7 +1193,7 @@ int num_cores_per_package() /* consistency checks */ /* more cores than cpus is not possible -> some cores are deactivated */ if (num>num_cpus()) num=num_cpus(); - /* if the number of packages is known this cann be checked for multi-socket systems, too + /* if the number of packages is known this can be checked for multi-socket systems, too NOTE depends on valid entries in sysfs */ if ((generic_num_packages()!=-1)&&(generic_num_packages()*num>num_cpus())) num=num_cpus()/generic_num_packages(); @@ -1185,6 +1211,7 @@ int num_threads_per_core() int num_threads_per_package() { + unsigned long long a,b,c,d; int num=-1; char tmp[16];