From 354ab22b931e3199f118fdf264bb895eda2fc62c Mon Sep 17 00:00:00 2001 From: Zihao Ye Date: Thu, 1 Feb 2024 02:19:55 +0800 Subject: [PATCH] [Doc] Documentation of Python APIs and tutorials on page layout (#90) --- .gitignore | 9 + docs/_static/FlashInfer-black-background.png | Bin 0 -> 100463 bytes docs/_static/FlashInfer-white-background.png | Bin 0 -> 101505 bytes docs/api/python/cascade.rst | 38 ++ docs/api/python/decode.rst | 26 ++ docs/api/python/page.rst | 16 + docs/api/python/prefill.rst | 27 ++ docs/conf.py | 44 +-- docs/index.rst | 26 +- docs/installation.rst | 47 +++ docs/requirements.txt | 12 +- docs/tutorials/kv_layout.rst | 98 +++++ docs/tutorials/recursive_attention.rst | 80 ++++ python/flashinfer/cascade.py | 323 +++++++++++++--- python/flashinfer/decode.py | 289 +++++++++++--- python/flashinfer/page.py | 47 ++- python/flashinfer/prefill.py | 385 +++++++++++++++++-- 17 files changed, 1279 insertions(+), 188 deletions(-) create mode 100644 docs/_static/FlashInfer-black-background.png create mode 100644 docs/_static/FlashInfer-white-background.png create mode 100644 docs/api/python/cascade.rst create mode 100644 docs/api/python/decode.rst create mode 100644 docs/api/python/page.rst create mode 100644 docs/api/python/prefill.rst create mode 100644 docs/installation.rst create mode 100644 docs/tutorials/kv_layout.rst create mode 100644 docs/tutorials/recursive_attention.rst diff --git a/.gitignore b/.gitignore index 1266124b..e42c8015 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,16 @@ python/csrc/generated/ python/flashinfer/_build_meta.py +# Generated documentation files +docs/generated + +# DS_Store files +.DS_store + +# Microbenchmark files microbenchmark/ + +# vscode .vscode/ # Byte-compiled / optimized / DLL files diff --git a/docs/_static/FlashInfer-black-background.png b/docs/_static/FlashInfer-black-background.png new file mode 100644 index 0000000000000000000000000000000000000000..79eccd9004f2d177a03d021cdf688b5615644345 GIT binary patch literal 100463 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ℑ?tzhFHY~W@qA|>wP-z;s>q()w-KUL%H!cLEDV! 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

AG5JyR{%TrdLp4KHg zT~t!w`0qZ)w&)@6}6r0{H{YLzfr-0j5j>cgp+k-pxv6XFf1ftWy`z1LRj9I zxo)t$k-;`Oh!{|rz(g&MI$Ka>*UyuX5WnXS=8O)!e(L^NJ3Sw?$1UBepCD_ z*VgiiI*16GFy!p>hO-(}6oEK%0}5n0A1TJWU625Y?b7o(9{HJv4n95ooNyj-eE?H{ z!~pqz@LbL8sRv0ju2Wj-i=73S=GJ4X;YcE7F)|7I@Stwzx>iO#GA2_b5TxrmfhARHx__Y2B@xakY-OCOz=g&5uhlSzZD<@Q9=2>^ zo*)CYyID1TRSz`gGZ?!-4OtLDhvOQB{Jynaa8ff8pd#L3Cn|lZH5_OP^yOb=9>fwA z;IU+zXTH|Cml<<8UUm7}3AhO*-h@`@wsyg*C$atFR>tywxD{l%lGaw3a z^ITNW?uh&ep9vXG4^2FtX5;>dOTP^Vg<+P9ESbzPE+-b=#C#XNfoxycuLM!sJ1fKx z*=pmJz!qN?VGw2GSP9=qj z{)g4{868&7In_!hJ%rQW1|I=NH+d2|=Ur6x~VK z>D9Zd-5nt5?!|BK!xtV`IqLlBpNxcWV%lE*9ZJm1(h1x1B~(!bd0gkz1KRhL;n72@MzKV|A@`_0&Wjt|JIGdy1sPo+RfKeKX;V@`N3U|bek)r8`C(ML zcEJ-gvhn?cYi;Ubq#;uBUF_hXj>>MVF8>-Tzl|)KaZamKL%^xL@k=6KR;cCUR!b4E zdLbm_cQVTMI#X>1!wmM_0O)zvJa&$VCM;m`LMApLHkGC2RH`@bvN(~}7xdvDwhGx4 zxkFg;A)`+TIIu)^2~s~M(@$D+`dV$ZHCsp+i>&9VKlSp!z4CdA7TVrct_FWLlc*kq zBpzme@UOIkigoodT4EHSUXGHK2*wVB$yW_>-5{fHeTQay!^x78|JaF13?cY5ctwr=kA)U6=u$zE%>( zw*dcsK%W$fP-%(#Ri`8O`91xbHd!l^8q2CsD;`2Owm?>(!#7KHQ)07;X8!zNf45i% z)cWOE3WZdK7&k%x?j$?A2VkIl&jA zY!_a~ewq}M+d|&xp4YmH&`bMQ!}s#CJ6Ii4yGCAQ&#?3r1F*c!VS&jZ)D#}na+pJgMvVs z^RB74rE39?Y(8u6mT$zEE%Iusx!<7+oCY+cSbth-2r zK)z;p5VsV5o5gD|f3Efz8643)z0E6lnY=Xb5r@&`OeySI2Y)~QBsrH_V>@{J*Svej zsb6BlGROb+5uCYCrq?IAG8)p2*AXs~)J{A?I1lU%riz^bzWR+v+a@_eIIDIwi%$Yg zW!aqYD<3t=k1fqC`E`~y$HJx#GIBM~2Q9kXhl5VAR;AbJJ_-k9UywHDm1W zISWT5LiZ6e}{B;|TtQ5M8<HQo#dqhF+mXg`( zc7i)v`YS3xmc+Z+WrUIReQ`>^DKubxbF4=sy}3cCUQKA-A9k%|s$wj}4I8+y`Ka{K ztEvB1Ns3pb_@pAb;at*j&78z{iEn}Fa7*Ig><@{ox~=Gnq`(c-jhoWRq*qi7abyay zdNf_9QM8%ShHjfHJPMV*Pl+n%+N)G{{@JQ+S!hH7&YkC(Y%YSC zrMBQ(=KbDQ<{(iD{J56+z#>>DDE-rSbCLUsYL10WJ@YvhEB`6NAb=T8Z>_koo}H@+ zm(6S}FTSp9J2xIUw|B6X_MDjO-{lP=_SU?by~AEhA0C!FD>gM6n3OgxRhmFW7d=%O z6y0jZBH&ikkuHl3UzG_QA)W9zFPr1aJ)iU2SC=dM6-^=<@vhS6@F5ZKunv%>Rl_#QJ%MTscrZ zKVX8nY)`j|aBTG#?nlu@oPO;3>wx570C?UVk0iPV@NBLz#fGAw*>2NoV!ZzGC)??P4WxR58LrmMU1Mm;*HQg+Mvv?#Y+ zEY@9VI0tSj1i+3^3?*4$#6)|kuAu1nN?46tV-$*j9Q5k~+|EqbN7>iRa_tfUBh;*YJ6r)82ct9(;%!#ps6IttFK+?vEhP@6PEbk_+>h z2NuN~73(DLHiDxnw5(d+YQ$KFsBeiaJXTkq544$6KP@~BS~wJSu$os`7N zV)moY@6U6p^Ngy8IPH$-mgL5+Qmt4S$t6~@jTITSA{4yr&f z(X&qI$h`oTmeqlCo~O@~3ERt0fgnbXXEXe3Sc!soyft6!vx9lnMH7nuVYK}VILiYNjW?-t-TduAJEwA5>=!LN8!b~ zy00&8b;M$RSVYcNz6rY()zTHGvpXwwbBP`7B8GQeG}?e+$`pv{6>fkk6lGcwy z7x@sN?BKe;-kZ2TZO{yDCj1 z1cu8Htm!B^J_H;Le5TZjK4#ZT0zOqT+!#gTsBvEW?N;P7w~`crn*Q%i9lP*;LpPUz zow8G$;_$&*<_qjW{^_OpA>u#a=(|I6u7ya9me7g^2snYkA)DCRrF-fBi`<=wMS-Fh zWUGLLhv|UT0|8uoeR@cEfOBKeV%ic zO$iI@)rWCokN6NLit#g&S8MIx>>eMSEg!%~hiM=G#GASGwwiioK-BINFvG5o$!Wf! zLG4AN9tY38%y#`(zG&<75~^L5Z`n8>A*abfHDL&pc+MS39J+QhMUlur?gcQ7X!Mv+}?Ck}K`ymYT)KzX4k?XP0ChlRN z%=9X_hu^6NXHo3eGN6y=a)&hTH$JH;e%xt!dXTSxd2mv{TWP4!a@}4lht{H)nK)Q@ zsde{Zo6QNsHN!r9;0+2gzL>?+pF-~J3CXM=+VanfaJh%QmiL;UF!n-79FLv&4c|Cb z1-v1Sf6j*};e7ISBbJVuJG#vE;{;WGF`g>zYB9+&nX3hzxIVD0&`w8ZsZ7LVS11=92Vg62FuWy||xqYB1K4;N|SM(%upitN`0j zC}u7t;*B<_k7u|fgZ`K?a?$5GvUq2X?>gB;B3mOiomwj9G$p;)hc21b_^jmNOlo>~ zeTdEs0B`#eg@$e=f7xqQzsr9+I~84(j-TxO({8`F+#Emn2X10~eoWPT1M_{9a)svh z%Uu-csV&Z#%WR)KJWp8WF1RJ1CAGqVKNzzUE9QDsh@V(R1c)528t5mPp5&t3hJ*FS zgebROd^sOK`ug2Tr8kg&_cMNXb3kEzuH1ocyAWZ@g42Zz7ZrWhoB61hjxy85`F=V5 zaV|A`YY{8)6f~8<76z7|$Wq6QoLKV*uoLqk4E|HEAjV!)G&~MHdIcr6Jh5rr%AGxZ z$&Qj`f2C+vZuU*|;~O*mK!2D?HQT}dfUK)TUY^BzB zylvfmxw(Tnrgm@#t>0_`H6II*2g~7826jI%;%7rW^{Lxt$iLTss3OieK38MP)s11p zI;?%z;t95-03?|7nrj1nY9FGWkjT0lBDoT{b(cPwm15v7?E~iMt7II+mao2LHKUK> zk#!eu7M{MGANa-V6lF*}73a~CVOm%PgX`5dcw9+-W1K1Am=zM#7x(+;C?DeW8yWiI zC8Ms1Z(gvL{u>qgd+D|v&iFg#>2;o)pbdwwZOmMKaR*n{^h5%OUoH3_F8+V2+^$22 z)IJ|BJWBma!|+&?eL~If>R(OApXXKZq8g#Y zIY%WYWAxnEXfreViU)z-ivz!=1xUYSX|QO^@aL^K+$I_OP+n3}leofI!9*KE28+9k z3evKlXkSY;(Gmz?cZXi-$}F$G?8w);+g>SqKhbP)x^?&Zd$~W=>@?gT4`nf@?Gmo$ zgsOmlUXjnggv5=M`hP_tqSvYpiKDydE^}&& z4XTKaB6?J9hOMaKHj?WWtWly@%?BV5rTZT12$khK8Du~!Uk{9>a*sKLtgMI~hLesl`lDW0vSdLt| zf9jk199xtAy=CN5{BdE1!q*aHyVuJomeNx}Hz)g*YGVnUUK zDvzd89pZfqpSfMuv{Iz8xPC5`i;G($hLXJzj2c!AE>)WIv6}0rai^NN{IvtfJQ5K2 zM#s(Z|1)G#`{c?+Y0erlbJQz`r?!40k{ti+T`FOL>|cUi`xJLsB1$0^AQ`6lh-WnN z4L5%?9-5u@tAQ(^G37BVU6_%RlR900qh;#XVV_B1t6rDr&GfsF`yr&NjWee76@p|} zqU&_s91rh$fvfEQYa~44#?!pM_MH=sl=<;j_cUVi6k73je-MC8-s*q6S&)ibV$~Ze!akle<)%q6syIDn8`WG1)rEKg^ z0citTZjH=0Y?mX`RsoW{PCh~B!~t7%2cG~OM1ZUl>do}MvmPL4TY8fgMx5njxE}0^ zq#E?V4;*-5OF*^Nxzwi@<39^aCtsHE(2RNd?X^TN4VjWhrdW@(_tUoX$C)j^d5X0g za);h2tv=bUkyRUUA58O(Z|U2)v0e=(u51r1%D9eRC*yudTk+w}tI7gCgl{qH)72}~ zwX9$^v*3B-P-Xr20NMM!cg)2AF#&CMJ;3PR+tfRJiiOojW)K+Te_r(Ats#S6cMf@? zGqa9PZ5wC2hvAkl3>Z51$3AgBF>))pHxWlA6je6l_nT=Qm08Rr{{rcEx@k6B%V!>Z zf^Egb--V@;`OE z$=cW$P*%M7Kr<$Z)%MVbHK40<&lc(y4YD@?{M&Shz-$flO?dt*Adz`|Q;GA*hC<*` zS#EQ8&42~YYq!B?`4}03`)I3LhJ7zMUGCI4q@WUjI4zCM+7rD|KV;dyQ=f~KNSQdG zJV2S|B%JI@l#QRD~&|#u>Y7`z157-_X5G zWrZzSSCX6gOZtwfNW||ZOj><&bLNx9%hEAZp9YP_kmFOZ21`RzSzlJkBiD}#Vq&XT zvY?%rN3ppk9Oa$Ojys=yY_1(aM=F)a6u{u zcTQFKoFum%+(y7AY{DaYTi%l3aH7LpS-{k2DO$X&;Ic~%fbRL?TK?AhZG~zyaQ}|L zAw_(>w&ntds*RKOzG*m3D!I=>j_OBKbJnGeq|gVSn;zc$93b12K+fGOYA&`UrK)b1 zUGX!>l7ZN<PutXSjkNLNS6{5FFnX6&5LbH|iPXI22R24p(Le9LhGY==*&rM!G@ z-<+6DP5oC`A|u|JptzBP-(!A2W%_+~;Wf9cgYui}(mp79#Lw{H1$!VRmBdA-UFK$z z`1qFiq$g##HtN}0k>3$b*vL$%ABMs28|Nu#6~s%lhS49X13e0o>JvYDH;zDW(T~Q^ zQMl!Xkh))7g0l!?1jbM-alEHtzmEt1Hj zlqhu5Q9$~pn1J-bk8c%gKL2Tl-v!M#Uj>vlD(m>?WzOE<28%$?hsYgniPwi^2W-JD zkIe7a$pNFjaxyirSQW(c=SRxD#$)j2r^1{>t2x{A5lnTVq^ofsoEk`T_}28jYUctu z4ztOrEKDfb)q-h;+)-ZM*Kp z-qG^L*v+xcwdDT)VWv(`&@lqvCo-4fQQfFK_!Uaq`xsys*YS2vcuz7bDhfTtsRW@B zyry%zT-44Oo0P~(ao%A3^k?f=C&M-_zZ1>OW<6=pB+@~Kbv!e4B!>QrYZW!a^1T0C>Nx}i zaI%>ryod~Qm0YN$;(z-(K+h4 zDO4}LcWqAcP-)}x9Z!*O+$j?Y@G=Ayx21`FEA@Zxsq6`L)1aXJ|hV)8jDw5m1N)P z`zmedLOuYfQZLL;Wn zcXQkC2+jK6vP5=1Q&N9oY*XT8#E0k(RUZLpq`cTKdM7BvC)z@m$?@fUpz-;YHE&`0 zx&v8;Ok~+~LE8JokL5F%l7m6GCEV9tmP5cT9mks^lH6}Lfy>2h%X-mpG0ob4{0HWI z@aw7^bQO}eF|o8=Zd+G~o%TsgVWntHG+pHKU+qJqzE~pa_{-+o&N6NO5$qF_7;DtV}gHk~j5)&9YF;x;OEuKM+1PJ~saj5xAB)S1V+$9f-oO z3hU?SKNU7|zull5M}8p)xKFRasb95gSYk}pf65sGx9pgB>+q%g8`a`NHvm)F@-ebv zt3lBv144IdDeCeOWo%&ec;eCi2r170)`>odiRQQuW|zXWi>w@c*x=H%WYik=*q+AT zs7rKgmG+Wv@2>L&^1i@&hp3v+mK+BUuxh_0TTkl8<{D1xoggmdX$H^Tb-GE2_-{$m z$B24%iF#tb4^IhEK48`A5_M>WFNUppMVw3Bd3CTMrOL=Z;nL}&<5qIQjLjTlZE=@u zt#ml507HQO_o7!S`SG3?8V^$1-)`Yrgprc;6%Z1ZZjBf%+6NzXyDCFr`?xyOtG6v% zkCq3ZiC>JRp#^iOfp2^7OqcWUCr8Ygp@DP9bbs^kOMM)ERL=#sV(_}`&!naSDg~~` zAR-&+mr^(J&3jaJOYdvUx?H>aEdi0$@U6mQ?rp0(15zG0aTm?(6&>@hOhiURLqR&r z(>2}op^qDHgS|5!L8np+sH;v~AM*C^zi>=N!5z+rs2XQ{&2)@)B70vscZeN;7N!N} zyFH6{+r10s824^f%z*HUZ>vQf{-f?z66<%jqO=2~;c`~^PXG{N(xv(dkhxJiko}Dz z(3iGyKfT#GWWTC1I6sPoreeHj@lS7OVj(ZeEXJk&lZ=R7QJizn*hRWoWc}H)9A}z! zS7khiSy@b6_Yu|wzjw@Np=i+!w=_O)vozkaP+wzq`fk zeELT|P#COVJ79dn5O)f5)BnidqzoWH6rFWfD=;n*3}tpr%M$>SLcJ7@(36O_n{!Oh zU$%WNK>wJlPo0~9>ve7YpW8zrsQ>(7l1Cm~kC~Pktvf2|KOwQDp@1{Lukh)1G3PLF z0CSr;j#`YpFZQ;T2QIs_z(F^`6T6mLWcLaxNLs+5Oy!t95yxV%@o2WGn%&$|@awkR z$Rv$dR2V&cIsfAd7qR1O*3}3=TVv^g>gu;&S_6l~H|_8MU{!kA)oE8%bj|LI155%h z-uXYSr{WX*T-ID*&pI1q9E{zTa9rGvu0gf{y~$_sTDyYFJIYy+%TIn*^zXOV2j_nO zhFc~we6Ri>3aI>lasi@FHVoyxA;W$}t`Jdse>AiEtzYc-NUkFN0`diyqu3Z2p<+`x_)tAcT#>`R~m6I~#BIV;vty_2st6|Hrpg2|1QhgTf)SC=n9_T1-r#0S8-eITjLMq2x? z##j15yJKc>{k9BCI|$Tk^yaR>y@L$b|3C)!p~F4Y1^frF?nORqWcQ>T=A^+fS5t}koK{gA|pyzBKJ_1hLAKu$^s=(UlPJv|o=0=B|W*Yi09 zx(V}q|41?P+9QvEQJW{A-QnV1Y~lD& zwq#`6YtwQ}jb6ki^~&BXo%w^`hpjeZTzojWS!V6e(*olrNNGw39QK!+KMuYF2H~$9 z)#aAn(j_CbB4DvPY`5CCDqCi@+@U`9Ck>Qjl&6<@&kz24Qi&o<1UUC(=RADPhOZTJ z$S^h=(&z|~P8@Cldm=P(8;tX2b7W?Bw2O^z={PuNKIn~RoAX1(1O*4qbKGmq8u~t- z)Zc7!3dR~}I6vzB_P6DT;EO$ci=*9jh8jJ0&S#);l9WDDR?3=W>E#mc3?E#C%dtxu$LX_Qs6pB8Aw{Oo^9D@16L^Uv$%m*Hz+ zdeT5sQ*~@9oePH;vKAsZ=yWPVrQ^MTDFhHSAbRV9VmbQmxeLv^4w-X_04_zhE7c5N zYu-F!WqNMsn6r!O5Hn%Lh2!})Qs(UQ;Y;?rK3vRFiZmJS6zNDHoZ z2v!7uV=x?l@KXfP7!w`_RIJB7mlb01uC!QH^xR%$EZCyI)w6dm{im_O0iYs&Gt224 zyPx5Angw^}nA9f)$l86QoFYFY=Xy_%QgE|h3dFIuHfQSQ>3z}D*L9Tuyzqg;NE)Q9 zv#gqjC82V*=-1GpSPdyE;*_%S0KxQE#L{kWH`GQL4`?KC)TZM*)LZbJpUfHj%LJpP z{dep3or(S#@=OFQY%uNQVvk6UAzMWynMD#hG;Dv6Co&b{SpIz&F-!7F8fE2G;q#dr{njL-ywo*o9!Ww3~>#qsN3#N+q@}j%HRndwU``8feiX?w*hj9ms}|Q z&p{sR$O-8~-xFWyYu+i66}iDyv4R0SrUWZBor$OC`2}jWT+G#S%j9FtSd4d6-mZiE zVsFb@KwRw6Ot_Yfu%h)L@VHOSqrg1fr$tvjUU2=A8)r z2OKP~>xmw$F>6=Xm~ZWscl4OpYCMF1G*fQf^N9G|~`NmAR~{fw*) zIWZN|MeF1*m}`rxJOg5qNzL}9!$v`I6y!se@mhI$<+lQRx&DeDr)LK|E9Ba({)%x!St|_AXSjDb#X^xQjoAIgj``Lq*c&yOR*6zE1=bt9DRbZEn zgP4#uQO|7cwB$MtiSh)b8(e9(D-)AB?&yHc*3uCh@o7+>a8zP*^8|iIgZEDYwB~Dn z#VU9%!)Rl!!%x>231;3I{jeQKisy2S>L$~EjlIi%$mKP-Rt0*B9jQVON0LD5p84#R zZ^RyYj``JR9(_v~tSJ~MDws>- zQC~X*Vl8IdVv~WMUc$OU*R#{mncai(@I1jocxBhId(}09xpN2PHk&5UPbSaY=mfgv zDO@GEHQU6uO{iN#zWq*N5D+HZiCi`MepJ-r6H& zb3MuvX2*kg35pk)8Jn&?iu(fgdcRy{QywWE1iLc|VbuxE9*A+by={#Tdtk~oP(K#1 z^)5gCq-{hHV_s-TD1Wv1tP&pFD4R=)A}I_)&WEIaFI8`(B*S!`v~}+@d+Cl?Fh6mm zCy35N%02c5Y#H*QTtd-WNy5L3smsMYX4|TMdB>@hDb6>i1Cz5{#T%{jJp1AAP>zZr zJh=dR4^%3Jq(X{ z%2YMS(6m*IUsJIgD5+W^8?!fh&6b#?V$G}+R9$KaHJHYxM74xpB-?=IfML~Lt{sKV zO+_1)V_80cbGE$s5WXYnV}39!A_2tWMK@v zdr9M5C6>#zB^I*Z{E6ckz*^&ty%#14lFA}>weF{ma`k3~!ZE|yg)}9t>M5=Q`M#B8)}{)FFVNEl*oZzxf59Xi)6%D709ESq$?^uyBugKF~ZWuL8zTEz`+GCP9;|OXmGs5nzUQnK?Z{8U8vMt80XA?$KM>yw2CbQOq;f>xf z*V>Js`Ejrc{^4Zj`f`}V;h)c&2BP=Dxab*d~v1`Jnm%DK4+bAU$qv3($Z}% z>2{Esy^w&M4QtooH+uc@k;8*nf(XLn1en-bzaQF=emliJJ;C)0=m zGhIw4tk#9A89SV0S6*-Je?d@bEs>d^FxlvL&?z!pCFvx>p0|QKnEqrSE5NaxXo`mt z$Z@@-rte0tt#2F+#-$wJ!&?ek_9xg*VBTi93`y#lL0&54{0LRMRtO}*IUyQsraA-^ z)gjs}Aoxd`&(t2OwP~vm0OOp`Ti=i)EKus~3UQ7tem*m$N6^u|s9A4QHbusa>iq7; zGn1r|@fkW%f0AE?wW0_|6Rsz5rs_!b{lA1#$rO5d*&vYlsipgwqZM;+Aqo^+qS8NT zD7w+h_z${5gk@M6lvfG|$tNPhS>{QntlTtX;PH28c_PywJZy$ss;oRW-D7{5QvC3@2uRozy}QSB+?16mvNYLqgj0QazB)U7gG7_ zbo@Yb*gu~TySsc640BK9GeN5A!OaT60hcie1~Ffnr?!EUAaO%OC;ZlifV%;$k;w2> zB`)ujWR!b_G50zqjKjy5BDfc*YDrhlQf}~iW8tk(g}bAl0h_vLfr@-2bYsBO?OC~t zCa_RYUyI*l;9H7b{Lw6o;6bN(LQXz`%BRTl*MO+n@yvGbE#*BB_T$CNE1)r8mha%) zSzTA2V@}cG&aay2Xz0=`-SSb?_%oYaZB`M=HgD6Wr;27{6pNK-wstP%=QurQ-Y}ma zZSUW7EW^i@g#|!0CJj-<^Qj2mluen>_;jlR$6H{J)Z;BWPF4a{Z5U!H?f(XZ-983j z@Y8=EuoCnCR??MJu6HSnxwt7AkkL+ui0MG_n}qmy4(!a<4CQIkQnGPNcu8tp|XATl1z47$eC zqbI+!dePJI{0u})&XE0Sp3Zm`5_D`kr3vcqrDw_?y{62jlTaegFLMtF=Lk$6V49Yo z_`>a|YSBZ#ee$D@kC~gdO+gENzTE)_RK(F-_a(i-a-Q-ZR(zyC7W`^=%UHnrL8ApP zo&g2Ggyhovk;~Z(9-`(S?*X+9zvy{yhv;993&EyusZARGd>%o1lm*t7qJU1g*ZD^8 z1;N~3fbYh#%5l(gGz98xMY3XIw!Ddsy$cf?pbtO4!2S+kI*5)Mib8J_?aDd~8Wtf`Yoo zC2-U?D}LoJsV5C0^OgNxm=4I}RG-bbY1Z^$_s&V|@kY^9Cb_i(OhBoGcTJ%64_&~UZhghze#yJMDm>Rql@YHxqv33A0g_A>Jx8`Z*+*_)930_k4_#DH{fOR=BqSd4F zCu~Nbz){5}nUJoKFyM0^tk~|M@%Z(CKEso(YL*)8^&p^D9*a#1eg91{rVp{Jn+yNd3(BjZ_{0oaWF=829OfV3{H z37Wm)9e4B}t0VpB4UJ$is6SMEaraB2#oUWW-QR)=1atkJR&6V>q(Zkj1)808b6~gU z%6<`eR5g;V;Ffe}!!yc9cEaEESDtv8{ z6xW?PT5AuY(@}%S=+~=NWIt+xhk4>Nn36TSV0w~QgfLwv-O}(LSK76NY7G8^CqYC2 z#8v@x>Af+^!h>b4*S#0O>q#fa=o|$s)DMMz!o_#Zhibgy16PMw16Qi0_l)Ph_$R`Q z47z#Go(cVa^!eDev%tGdrmdX?`6b~D1=VdUNS9E|s1oX|bzOgd?t=DHKbN0?wK`UNXKt%VNitj^h1IJWPk8=|7Vtj@b#6y=f ziUo{cPjN{wWJ;xa>JC7myF0S`naalv#*+J+RzfsZ>qMOFh;iL59XE%)T}He<{q$pgWMvnl+L(7@3d%Qo7UO&jooPPv8VLoxZ1S z%X>c$*vruEK6(DPU+0n%R@?zxw6QlBGUokV(lJ~>>wF+hH);Cfj zQ>q-jYh?)1exCZ1sMrFx+9cEM5Doc!JAltV%qLV@pU?TRz8Ghske2^BfRUO*@wM5>~5gUaEp@~n^tSZy%4bDUbZziw~fkK#fW-N1&p0Obsa%h`TynThBmAljI zL-S6~o2N2;o;ifOP>0>Jn*WKUBG%?|9Hb3&T zK3NqH_Vunw8cWRbao+s~=`Q;@O=8A$ayANiRB&rf;Dcs`f0N0pR0T#01Sk<6IVr`; z%=uA+Y>-Xz9#;6D%UK+8_`l2fe6TLVrO=d8Y%RaI>~#iA7X*zHzLPoD8m)YvD9i*c zo3ji}t%clrb>(4J718WSCpF@eKnDub(7|0@-*#J^w$y(k5^$G3@u$Zl8@4B$;RfYh zC+PKHtGx^}pJ!}V6+QT8aE|^gBc+TH3w_$E8$YYke?D;XUQ#wt*5* z(Dd_h)=KrM7n3!dqh0IXcFh)_+F9fvIk_w3bhe zm|>fSH($L7Yuub?evJkbs{RCrFAq9t9MI5wYC#3Xbht{u0qJRI&aJ-5$JeN=`oPz( z?Y;7Sh~Y|xKZjm-s_24lLMnh3(``(Ek-DYxW(4?`Q zMQn(MUxj)maj%{tkK1Kfuod5BIYyf(7k+f^`tFZ~plMHN{XoJ1 z$z5*k_!w@oX=U@o%P@Ou*RWQU_pETOqQPK>Ht^m8$RmJ9B`%h^rzjctko!SNj(f&} zpM@N?8^xc`Cutw2{eWtj3M(RJ10Zx6s%)%FZ@d{J+{tDHclGJMQ6b3A-ulj?Zi?RN z&f;CEqN8F=t#W&34j|{331MOMv)lS_JYv6Dbal4~o4BWnFI zGQkd*+5hpCOE>BM+<};kAqm$Dxg+8Co+MEb$KnBP4Gqy2)%vxc_9ttMJG}sN=>2e- zZGEf#0MkTJK|#VDfI+PB7Q&AilnhfC7z=tYC|P&SRQm+sf+h*7HK#J}rg^NM|~Rnw*(@?hri z+1dl0mh=33tKHZ2b_lEn6fU}1gs|d~vqC-WLmSJb8rGAeR z_agPHaG8zPcUk-c+uWkURlvZ{G_*^T{N+#f9sdv3JQ0*ZMM`cq_+QS*fSsmFnZI{n z-}6tE%v3W!`|U!U=~4f5+5Q;e;Q{Gl>9{1jdYO-Bz<~GQsW0n5+UhrJ9TjfD!?4W1 zhTz*OGKGkrh8A`=F03!o^9;~L2m%I<*b$(c;kd+gl17cd#nYfZ``G zu1^?N4mN$(T`^r#6QSM}nt4T~?4&37RGq&ioAqUrzJ zQ&q61U8!rY^!%Lw)p@=p68l7w_9=2M>F&ifxU~XVJy_OvFrJ5z15jRbHes*HU-aUK zOS!!e8J9aNr>M}gf3!&~<9@dH>O#;-=jXlkYfS1Oz&P4dkA`$pna|2^L^%;p9h&rk zoNEqWvJ!{OT91xfaa2&%JZLBo$snD-ej2h5Hr(6EGsy*DP-<4d{TtqIla|Udj-F8k zzTl4*px&xkwG>E_NWW<4&J+>I1Z#`3{HOgN2(O0SNuKCR1ai*e~5oFD=QZH_DC7|U8W zGBa6|s0al}+D1a+f-^Kf+3WNHJ*m^zN?{Dh@a&~KfljLiOY9yWlUCd_vNli7n5exW zPF*Uh9tS~O+}B!|1dcdQDgrrDc0&QN58uvxeQ=W8*UZAmE%@5NJkch8E6|RH&Jj2O z`=pT8*~`FiD38WM$E8g!I$U$Z3$7G6tpOd|N0E zqozEq=2a^aRMyOZz_G7Hbv{2C;`2S`)?V6_0 z7*Ks2p*%&nzTlO(6+)|1Lj4d~a2 zxq{LCu<-EbJ*4gA; zeGqVDuGCMCiP|i9DLGV2)Ye>(@bAp>sZ9-f_qe9+$YSaJ@d`^&!<*r_`AC z<`vJGYp&n3HOB=(SqD$^FB4>C4BH8?xgNI+P|5dpZ%7ehp(oPAdhp*eo-xh*hd$wp z`*i;oejcj=YSq*{Tbwii`-G2_mxoZX>U&nFVv2!*o4V2}>dtPK%V%4qdN${mrhcH- zV{{cHor`28APAyn`*c;-SPw8gk=E;C*G;;$)Pa`dahC~WelGzX8s}qW1Phk?>6LNIrOYTX&Al^(CDs(bIu z?Ta%Xga&#*>7{vEZ13LfRG_gishrU-mL$(z0~yap1Cga8zb^NZ87vE6!Q`_=HLSY} zQmo^YMSjccCV_^(_$p1kF>%(c4;{BV8gg85Dy#9Xqzil`L~lK8_Y{f88NSdo;q|2* zXzpF`JA4J?V{yUDRn5c_6Phg6hMhLNfqyUz3390Tv7~7aSsD7M?)sn57YdR5G+!IN z8y8diW1Zy3-zTJAH0W2DsHJP>KTz&BU}t`$)M|We{C#9*RCYwFdYWfvA5Ga4F(#USM_PbpMUWQBx_4T=N6OlOTMZ$Ae|BjX$*`J zf!A9ybaceVQTQ}Qp(;!%P`!*wzn+NE)OoYaMQWZvSzXrU^$hs2&Ohb}YTw&Q3mcK* zj015sFBdCZxj0V0@Ts-Csz@Ider0PS^M@CwOSau7`!ds^&cw{8gIlvV0~BrlIUV)6z{^CT&YJrUm3 zn}L&dWK8KPo8)#(#Oc z5YF(B@ZAX|mD}s43?-K|j9sUn1&!M}2XiJnjZ39)Kvb(=8NPM({+@k*{Ob}A6g4WX zXUhJLtc9U>&FSV6Qd!<&b-hy8*XU5%vU(0fx(VbfE_nE<8{9n`I|cA$gt!87r#1p5 zJ=Fl1zW#?AovGo!5W4VF-(Zw@aR1ZOV#D_C|BrCLVWaGQ6>pkWl~n4C;6p~m6zyK! z-YN+{1w!ImluI?)InBk)Jx{xPBB&i~yBTkB!(wWs^>i#^sCNwhu-+RpbYZCLZO1xU ztG7ztrNSClm*LpkD6jP}qnGRU<`=kM(Djhq6J=6f@0A=Z0^+r1GGo0-S!+~m)92?v zIQ}xsYW$Ifq{dXEw^lvR_}n7KGtNoA{i!n?KwpYGf)QC(-?$m5pQXK!(G~Cf`O{V) zA~^D@f5!F&S%T%sKb>N!e^AH?8bN{fxUWyw`L^USma;DfLE!>Hchj4fBj#XCD8;xX z!=<8yMeGF%&5RZa(^*^@q=~S|5gnC0Z1#Dpz4yW_%qV1HiIhDI&wrZg*_SCZneH&} zm-aF3XrSmJp<0^N?>w57q_@uuMbKcNZmP2+HO4toyW@6{)@cCD?!@ju6Kk#HH!l>z z)ssf4wkAX0?%xYF5ZkYzrg_p?lYgr;2+lmJ$v;-Q`%LA#3kiRaBS}49Q%cmSXg`xJ zn>hDR=`dz0&!%{Uorxp?$abXHw&-a1hrI&gnz|LLc+Y(AL*s1Qady6}`WM)B(i+P7AZdP(zbIm!nzQK9}=* z(eedGpE#+T_xtk(%#*m2ac;_NEAcg`VXDxlSiN;Vm_J%07lHHqD3LHwdqeeNcYDn^rrO& zJraIM=OelOr8BhA=-mw7NiSY};U5~sBe8Yx)}}E5UO>MDzK1SUIqu!jRZ{*Now$L7vIg?(ECb);?y^0Q9j4O9 zNg;7mC48#~J}NvO)CC>TYgXt)TVb*6aSN6EqQ5H{Rrj8wDB<0`eVkt^Cs+ z+QfE3Sp!wS$zk{dT#@P$Bb`~bcQcMYET;(50C>(ydP~xinZ?%~2!C>>p`GRNgW*&f z>pHtoNwX?gE3XSRMwB?pJ}@Q*SwsDgZ5Mb7&gQ-;t2<8(ZscA9&zQOwxg>AG4jOiM7A8On=Zt;!7hH3rAD=~4Uw zk9tUP=a(jAXTbAV3aC_NCCa(tpt9eh{n@6co>}F26tKMa0J)X-<2e+x#R{XAXKF zehQ>S!_MxdMAftYq(m*JXA7s~K#Q90Ks&X)1N{VMgE8C~xGmau^q|ML$nbX(ls6!; z&cxwI5bv+4&&Fpvo-w=|!6~FJ@_sb2(%SPoKYmpQ1bl7US{1oqd#62hKkf6&GWI!l#0){(7E4H zIZ1tJNgklL(@npv=Kpmj>R^QC&A#3Q3r;#y$)<^OpD zFKB55b6guiJ>T8$+0vy`FIt-#1s-4bjCgI8(*c7kL{AMo7MjcrJ{Qe#kmG9@^ZWv; zzWr2=O^Ol|Ttd!;t8O+ty5YS3B3XjHl)?5R%q3$uZBXl^W$Im|8K|{-k#|{wB1R43 zqk5HK%^i@#@XBOIan@hx3EtzfIKB#TE>T}3=xTi>-V6C)wo+I^Ncr8bZw^i;l=e<_ z-(|3IffB~@3WMhB2-dYXz*ClQ4XXHNmjf9C84xxTTm`@|goJuouGoa}YR=R1uvAga z6XWPA*?~x?b+dn;G-gk~4^JA|7kj}v3RE|385ja}^FF6Ajp=_*Si~+e-2PaFbi4Rr zsuTVN)RFOvWznE>_D*Wi&PeK*?!QGH059O;E|#>j8Oi^3?)edquc?sa^Q>DG`psYM zCQ}oQM=o+5)0{uZ5o1QFEUz4t=Q9MdFAl6LXw($k&3Gj~69djPeg7%y8%R5ewbrG# z1+yWn+kk5vmOTEKSzP^okCg68HKY1l=;6t`z3=6T8>I0x7RH__w7kRvyXoR)?;bSw z-om)TL)d=IML5rslvo#l5=QZ{kSpvh7F1e`1M)3w$Kc}|W-(2~8{`)T^ylB0V5LNL z=z>4Z<6j{fTU!jyzcP|B!{4G2jC}99~Ic4QSIuw+A zN*p?aY?%#WBKwDVg5d-!i_SW4z`ijasTyxvdz@!9xE`tjN(ViXMziu!aFwc{FaL9h zFPH#IxUP#Y4$&WkuYPK(09|f`Vj`T|?OsjfE$0UN23=Mcp}J=yKsGT;aIsRJhBE6d zr7??fP2^dyi8Gj5Y;3}VZ7n|?9`%^)ejW=HuC+6-SG{fm7mc3yOAP%%QH5p$4=}&8 zloAl71#9M6M}AO11ZMAnqK|eHU3}@avg^kGh-wdYHHPII2BpS|Hk0e?e629n?4yrg z510hEE+@JNUdNqa76R(NCs8{f#d)vrAwn3?8`Frb! zvDCbtP1q5`4qBdVWJg1LA+<2kyMRL&Efqv~oV~kse2BKY4;-yUc|J_yfuxEx$oO5g z9ftz#R1d&cZey2B2RfEgQ^x~(fZ6gONlI(geIH;rpu4f%5RO%cc2O6rp z4`rT2rO|bxsaLJ*K_fNM2sVrG^$Mj5kp6B;BjNBL01}LT1DDub6vbQAOp4fw;A(tjfO1_fz8$`QqHmUL}PZA3+W4(=6 z!yEi)E$9;Bl>$pQf+m}G6zr|xSYp}2WO`s!Rr>wwy4JfgdX`}#I7+VwynkcVjtpY` zo!b1~3qyPq+y&Og)p$!9k7e!PbwEyxBzdZ+SPyzgK?%kHbX3Trm~h^mkPivAl*YXC z7_IIKOgTHooebJtCCIE*t@xC#_`pmC3ceTZoNp1>GbE7HrfmBU55>p~J(SC=t}6{l z0fiQ~*NbX?>VQ(q3tA89o=wdQuM1Q<#+IqDTiHEow67J$pNK;$S6kOR7oJ3%JMYQo;cwX1@*EFC{x?o-JA>}8TPy;%87Gv5WvNM*h&2_Hs%^MIWE1zRSbDv)~khYv9 zPJgqk6otS8oOTxZqQZuchcIAsmAx>TeICT)jwf|84ew5CArteMqQaKU1S)cLXN@{2u^x?-Up~ph{+ze9QPE z4=lIVSl7|L?jaK8&7!yImv)!}2J&<^VeO`Hj(1qJLUlF;u920}4pT#*yB|gQgua5J zX^3``2YnJ>?PM`*Xvudz%h~RqZ2N~H@LKInn`G7M5g5Zca<1QbP^H)dc*ix9kIKZp z;EVRM0pAV*yu?YL7#kAGsp*bIo?IUer-}Gw6Q)Rx$iB{F_-NSXQp-aPGurN9a4Q$a z11Gx+^I_AT*ev*O1Sd0sRm*Ukv6WksSBU1=OEvC8un<1xKm$J({Td-cIr(uV`Bh3; zby4FS|4tdYU*prw=?^Z?(MgRzugW>)Nf}O+86KH4|1glSrJnm*%?NaH%FVY@6O`6^ z&?&8&!`7%J5s<=2Rf}z}JZ%GgWCE$%=ft2u>oczKK9CeA!{c7poJ8DO{l1|egYBAh zt{l$?EVTYH%~v4O6g$oyL+c4rOUsY0-E+AX@lp}tcXhyV30)6cjc=?M7yV~lBGjmM zZ<793BfI$+sH&^f`BXTEx>(`!s&4A$Mqe|Z86|2tGiqmOlQW!JwQ;$PY2t$SpNwKM z(3a8h_>bR{XLGytNw5xFLPwwG-R@TzV`xUEFG0z7NbXp%mwCYZ&aX4aCjt|?5QK%^ z=9_vDZ0#YK`=nL52R1ypHeP?O7Dhmm*Pi+;1a6i0|I<||oTm*BQLCSixKhq^qvkzT z9~qSfxsI+mzP-|_U0f08RSsMRXaw7FY1e}70VtLnSyUIgRXuKcDIE&ZJF7r)Vl zS=G29#_-i~|A?S{+VLT5Qub*_c$yOrF>=y6ZBsxo(#B-T?hoar0pv{(3u;D-HCbQG zVT+d@1V(Qqj_}5V0yH4JhC1N_c6`l0YjAOoBvU>q3w zKftX40JpaShFj>=TC8QNCxI6R$9}XURAK%{_wlJ!0Jw)O3EE-MdF{KyJ6j&tX3*fy zm`&_gHKJASSNl3iW`r8|HoK_h`hL&uc1Q-@1rGx~fHi11=M|?li{D0GTy8B45e73n zL3S4Jr6XoSbWNnDG^A?AL2PPFWk^mlq_7@|Q+*%iCN+Bj9Mj0D7J+?#Kak_)B_#op zKWKfsRCm#l$z#`>y~n=2!5EmV%GRwa3@?qa~4Py07M;Z+-!@~@Pvg>Y=@ zzava{H{kh-F_s9o3{&RhW%(E9KTd_W8AlX3~ovDSt8-6`Q^`w%~xS-2_PXN zl~wB=?dAj&k6xB9O@jT&US@jSy!X{QD^r1zDuixjj-dK}wGQxMDTBQ3{`pCmD?Qi= z04vG0J3;d#P*@0SItMa+Q|JWUx?K}k_B&!pd;OlN!7bAUYf77?Cgv?kw*~oBW~Q*ZjFzt(sN#1;HTyRPUkDHo-@-*vxg@OsO_ii?dGXi z-N&IFlX+mjrtmO_vq<6WXDE8bc0uI%Jp_C4(J$O>PWx#>N72G$nt_1OZUHkn_xqM} z#>&Uflgr&JVT48&lhTJI+d|k3=>UTXX=muRiQ`B5{Tm2U!7qQW^1bDN$IN~ELw6jel5j5kKpg#@t-0U_QpWfWXdevnG5MsvrJAEGcV}FvC)>gMj z>uZGk6s0D3W#c1`dG759g`2MYGH>~JA|PSMlZAzvjwkY!Yp4g~jsEQGCl4)pK`!6P zF4gYu<*G$9VD22&gURd2^b%JWZ>T$^u7GShRK;?+tE#@t5gYyrtF7k%`99;n_-H&e z{!~|$UsKwq)o#miRuwO-X_N@z# zveIeg55}7p=tjN1Qu z&2;ms=Jj@RcHQwuag;CPyE|4f=!9rWik+&E%jLCTZO8EzcV`aAv}U*^Z{xwjT~+(l z)#PY}i_CPqJD>Z<`%eA=MIpzZhp-(ESn)BV$=&3tynYBw=yP@%vYP3ryc7L~$WM{4 zs@>uz;Hv5YDV$rJrG^~fe$8e)%OrPo$-2z)u-JBw{Mha{qfZ_`gLl7?NJ2loH5ZDa zF^QAjnhm2Y*ze6@$CcgRa%w74ezZj^#6-76`>q|;4z?8d50n{jOCPiwe;S>J1JgtC za~+k#45fqCy;@HC4}Ex{)x5&b4IJ^ph)7sjJOpF!ZQzIyMz~M#;bl; z38);@)os)$%ldc(NrhKfj^FkJn0zJxMCdTtUuqUY9=r~FX4#VwD>M7y$h9pv4qoAJoqZF06EgD(xGxtT=4 zh$E~tM`NSYi^f|h(LE#wN%zr_6&OiGh>y7`Oj{h$Kj*W&yjG_jJiWV9HThKKzdO>v zKpSrJV;#P|EOm#Itz<`g@iw~9y{8r|IsB>p<1G7}H^NTuHyc#kojBNUZ)`t^hg?Z+ zM%1-w#|aFye#{d+;Xpg$ zQxB8d?HcV#S1~ZH2gwYKRc2#|8j9;p>bXC3f9k1mz=)pO(iXRAor>@WPo^43a zFrG@8sVa~;wi6qP%N{D1zcAbt2XXrw$UkCcU}#Y@nDZ6?EMtib6-ym~JUAL#OczsK zRiqfIlm5(5Z@NPN0i0Jo|IWsnM+v6UZ}>D%L=_$bU3);QjM%&p4V^dM?IYQXYq9C7 zd9svM|3$3i_78*qjQb}}Q2|;zZ9lH+Ct!T}MBVo}hmT{P$S0;b_n|h|%ga0|FPFTQ z{jNGXv}CJq+|R`$jicX;tUIv1dWg*%nkyPzcVK6~tvG3{bKk%H1NK`E@dx;N8_EB^ z{s+@hw$RGFXp@e7>NlS|Xmkn{rxou-8*>hvakrxne(k-A85o5W!Ddv2N3I2)p-Vib zNcpA}e*t-OL*|v0JS&H@hK79W8|nYPv0Q;hkgMYXC)@2ZdfW6x+;=bOXyY#&?GK zNB{Pt`FIDsp{0r;!TZ=Jh4LaCm7{YGR_P^~L6LZSw7oIUk@a%bFd3rv)^JuSyUOW< zF{cQ5Yc5(SPL1ozmcb_o_F#;4M&&pC`<|AS=|)?i2l@gl@o$Q+oQ+2CMaL2Cbgv8B zgYxc9mH2B_a*HbNXTIj9_5{jjo7L@bI4ZTurF-I{3usO8aOO;p-nD~ zEC~i(4xM}JFp>R@1#^{%;@3RUoG?-c)+wIi`5YJ`0b_#|cg?-Tmc#Ul+vF zm_5L)T~&M2JRoQh>1{>6vip;jH1=0H<=YNyWhi82!kCn`j>N3nd>+cLuE!%6vcg<6 zc&mkzG^>JkVp6fji*Ea`}jz2vD(<^d{Y!jsD=r9|wyagH2-BVj&XVVz0c} zPoRPp%~gFG{*D@1j%8#}AI>Z2yXvRRfRS~SP)~`z!&aM3K zW#TshW8XZy=%{|{cFz41KX3WUe*r^)@g+1Bn_jHV>mCRg&3|tQ`7DHuV~Qie8(dz? zqC4`r1zxUf;@Ts$cDL2@?a`<1K*VC+_)uOBd3#fa!xI3OiFDQ@TZn_mbOy#`dH)v9 zn$k5H{qe|=M1$s2;&+m_x$dgVWg}63Q6t!_$|nNT{@7}{nW|L0DKdKjR$1LRHYQ3i zG`CKJOEe^W^}Tc}POY0Ovt{WHVdYA%&m^ocCZn_DYA|1CG9NJov~w0lfji~k1M{!?KC zU%2xfh+(m^ut9b|laRB9wB_U1Hy1)>;8dTmP*sCR5-n1fjdGI>B?4pvue~Q#a%jHt z*%FURFbK2C^Y~WB{e8d95qbB|ZLUp0dv9_%g@Hl+OK>1wJHb7MP!@bHLWO!`ZnL(^ z^^9Ocb(Dn>{@}$c(SqmAy-)yt|Or4yQZT@G)(DBup3zBj021b6ehD#jf8 zQ{cb9;D`7Tw$RIS6>^GBtE+_{`fe3HvP5=N&MA8{3RwjxSWte;}Xx6;=Yq*=AL;ZN)?*soz@v_w>@v z{JDQ*2iIWP4xcHVF!67uk$K*9=@88=atY;7SDA1NN5?)TO4T#G{Ylze}*;g-SjK3!`Nh}IL5Kw zb-IW0+D52G`+Yp*>AIDoA}zDFlXH3LkX+r))rV#dZ#^kbI?1yOTkq!#zi~lL=LZI5 zf}Bu^cIh(mV?AIbc;jvyD#7({uR;rU8o~Q81*Vw{J1~sd6YY(acV9T8o-Y#z;VD0a zaz?)RYMZXR_z3>gHeG-5Vt{NT;?Bl>>FAWY@^p${>R6AzB#sMu>`0V`#(xKBaSVK8 zhd5u>4nbhSU9qC1X7JkQGqTsMig+LT91?Ple0=tsDF{05Dl6H6VSo4FM&`&?)neXi z@kO{qbV>cH|Y&}ok(GMcPg)L)2sHj`R$@b(^sg14yA7fOXjsMuyzY&LPK?`__m zF`kEaM|tIuWIkT2l{@bE6gmD}MHlL_1Gatgzh4VE1h#$6@8;r|N2f62wIK$(Ui1#` zkpOwR=>;xL^2m!ItHrgWlPs6RkVW_}ODczW6XghbZVCM`*M{^5qPbsWT&|!p!-;=u zD9%NPfbZiva?QRaTfgIOs!%Psegz@=&e)@xBTMyCcS>*bblIj4a}RDb6gZ@eX`gkH z`RHnvbKk!l4CNM-H95q=JWg({?-b9xH-#?C__>U?=3xKt+ke~vZ!&6^2nH_WI9P?- zX3?hkjz?ctmL5HXo z%ZDF&Y;fe(vICpSZ6-_#aRl^Y=z9DbSbTf2xx>PU@bLe(^&=bA1Me3S`UzTG#fK8q*kwA=?y22(5ChvgK!7Q+-N}e?^dh=D}{wDK)PSXLhy{3lu+oT z*TZ-S4>lMfFyI6txLAPYZF7ozv7YcSq$A!)=Z&np(~0VrOVmp~L&yU@ZioBASkD=e z8*g~S6ZUpTL54;U-4eX}g&*20t}@F!qv>=>qin=dk>Z2`cu@0#p=?0Azfu`qF84*b zn$ekq9>B2y{7LFRjB)C{Kroa&1U4T9Hh*2Fw|>V7`OdJO#Xqjsh?Sr5_atv{3Xe|h z*Qltk@ete|;Dc7{MP76jMgSh5yZ7eYmdx-KS5)@xsMiC^za6=8NmeCrZ?Na>^>e(? z=hsKSipMwYeEH|YGL3s{E$L#n^IU^GxsJf|2jNJ8L+s*`@F=&ef{`BO)s3Al)O2~{ zhb*HppD~f!BURGnWfnDoL1VeqjeKJ@rQQ$V-|>JcY4InH9d}&)SiZbHh|J1|kX^^d zVShRIzML?&j2_Gp5OP+IHj3Us>%VCpMBa}b`ssxOFzOI0^T8DQk)?n8%<7G%@^zJm zSeP76u?;v5D@V&WG4ODTfhG5psY|>LnHTvlu2o~@4gV1vG-J-sTL6)S2lIK= zK5<86xjQc{{GYC_J)Y_P|93i_Z|Ooq7e!?{)#;-8s$7O;|D{r>f^_viC@yp2=lHAu) z+-&@Ic4i!Wf7k+>pmdas8_Zv3fyetzi*Te8AYFOIrGIwbIwFhihuOq_~M{K6%e+(PNbt#d`3_b}kin z!ozbYEygo`V=FyIr`_L%vdX&*3)*rD+MI$j2v=(^G`c3;uJ`#@%Sw=&hWJ{wQ$nFY zof$R2X!?;?DU7*Ol4%`Bs7GwZkA-9u$Z{s-B9E~ycR_cb9*6*$1y21nPfd)Yr~gf7 zwL$*m1s7GY?_Fp-G9H#-0QoX2Jp`vuShDWcZ{)`3RzZR*F9gZf@|N{YTD`FYF=_^S z`ru+iGX`BLvj>sjrHIaLcM7)f_)wD-4`)~-<$ecd#FmFx6lY0XropA{*o3QWtE~8d zo}2=o>H&+TlHAU>!Tck^EJ*ZQMNJ6&h-zolT<(e{<~%}708H}v0!K(JIig@M`?_vh z*zP?3QzrV2$?B>Rk5E&4-!W>(*tE&Ll=_jq#Ri1wKk!L+UJ!B>>B1&A9$h*U+!Ht@ zTrUaYA1P>Se(y<(nS$r2_;KE7n8k*bE76Ma)D5;zim5_Pn__45z&XsCx1%_A3#vmb zO9uaH8^!sqpX9%wgb)=zd=Y4M&*MS`l#`TVKd+dL>~ps1s?9iJn)7KAJ(nk!efysM zf&~}X`~{EkL*&tja9%@iDo+7hVi4IjTN)KTZ7zsVWqD^DmchNt9?u2D%z+cTDOlUwgIR_UVa z#*{(tyFV|QlKBc9*Ym80CikIm+DfxcP@T4oqcMWCh%!%s4VMzj8J5Fpx&$YQa z<0H(BL#>o&!}0sPo0c&9$z37_X|O9uaKR21e_QJ~P#45bL!2r$@oWr9=iam%5%}`R z8`GsS-^uHNuJ^HP*La?i)ATb_$fsgV+1CTpNRvnXQuM3U?|8B#0rhvB`nROWE+xGY zqk?HgQODRaGQeqCR|s#l3~PRQ7UQnL0K#sa_APDzrG(1LTol( zC}ntezm?(yIR!C|XXM%aBUYkjLbqI1$02V{#sh5^|Mpqp+waQ|@sRHvOy}|S#gQaP zBG0WSv(hS%??Od%hJimBrBN&*6*eo_C@Z7X4=1_rM?K4mcSUnY1@gywtE-hBGCtX^ z^pGoTrLjmimX-Os@=$BvPDdOSW115=PI9MJM+kXN^Xa3{0;EJnUkhccmOG8tiS}=N z#)|9;DvlcLq8a8Wfv>wR(?|~u^g9*n(hMTIU&iAD40+g_a?IfoJ#)_$8oN4;uUsi- zy9Dfy96K{_r}MismejkSAK|2Ns4+JpYig8&SPZ5i^d!4I$8BVM%0vq}B<6(41hKyd z$Zs{)p5ngO&`1||i>Gv68e9!xqnNo9)*=76bJU^0H}e`hQ3^L*Ap|_Bb|T*$3o#Qn zdSWHNqLE5_$fH3989Lhh&hkT;Ouj+22HP%a1+N-D-UW^dV%lVE++f$X&1Dm@a*+Hs zwe8#1fzS@=0Dd9n#3o3_=Wn}@zY=Wm9&8a|`-F#F{rG_ElCWsPk`ThQ9!ZD10o3hm zmJxN|GL8MA-J&xN1&@flO>X^h9Sc=e0F|o0e$L#=dVEW?T4?c&Ro$i_Rx)_zaLsC# zzV=Cl_+7Qe8w>`dE1SD7munPTbF=<&XIy0gJ@W&UCIC3^-0W#94q=-4v_D(R51587 z?$6aizAHABNDR~@(W|p5Tl%*?+cfu{6lxPg)Gw(JNzuQgqjwi2`Ox$DHTRqf>Fe2y zyvw41XhBSt=iJV*-^f^NPQqQ8UgTXTi{C!#?X8SBi!E}>6&)SPs!ipSW4O{d98SOJ z8f6zJv);n~uScmbtn4J5=*E6rL&C_?k#$*npN=5ky%+gg#_yQ7Sml2pyl{Q&nXMH@ z@AeE;vXofRJ3)SRl;0w>$I3uNRAGCFg>mMgy(QQWE6X~hIL~fBEtIa5Co8VtflkE% zNWZgLRYQj~ZK2~*-AMc4+xos%V87%V;@qI~;n^cQZtA#dgiT!uC*Chkx)Q_|*xVIh zV82^7wfWf5*dW9lbn(9(97#XfH9VF5RJ29@e#J&CG>k$V0BInR*2!!%r*MdpYe{^v&kAvoSCLE%n=#VSa?*4d^IIQEfVSyP?-BVqpA*=n>$}$;9{wm#C-oll5o%93`XbcU+x60r=Ug0feHDcYkz@<9xy5Omph@E7}Xj(Q={{* z2R0D;tH$-*&BNNs8`%$t_lEEBDliV{>iQl&0^V1*ZeNUhUbe3)#c>xXQ5#i54FB3yF+PZerofpx!K; z1L)Z)LkC@salN%PnpHylf6E~Lw+pnjxATUZ5Ujb9D{9e+x%mgf%1eH6=l_!t>F*Fc zJ$d$Y?(AE045ph;bO?5@4m8bitIIDJ{!H~4%WkihB%16bD(;Q3rO82`gV#Y9t|lG} zlEwJSeP)iay(*OVNGV&;1Xtmo5Qv{k1~({b)ka$_sAmsa-Zs2qb87= z;Z0m19RdJ;tjC0^2oW{&1$JU?DB}B(1K-~kV$LUKnQktd7CZ%*ns{Y(C}}CuY6cX& z2Tm;6KVgYz#i-`S=1UF_cOTz3M-l;vpELbFQ|^_0aiuT5#Mwk4=ewFUiVx%3S9rxQe?3;MISLUC(Hc460csBA20rvAe#pK#iF}g`pp^JA9gNG z2spzjHkg_{>udU|KUwVV9g(}|UI{T8E7B`m>$2fO`BZYVl?yLVRE|5A%l}~2e!4f0 z@G<#vmq*?KE$fZU+y}z!9Vbd&mhy+BvsGmm8tW|>pEv#Q7Oesrwk}p$|J>%q$A?nx zZZOrpv1g?(Yf;?u(E9-H@{|w#skbQchbbMYrfu4c3Xwc0b<2}oPMAwsPnzc@7ej4< zoY*PHq#5F2UCDA(XHm6A@d;igzk?}&a`%AZRMqN?##i+cOmmo==;&!Z`d$Lz0Fabl zIw81@$t^zDlyB$@&>vo~VDa@MhiyEBQE|N>-alm?PN6xNgK{0ld-VNy(Rr)UO^bM~ zg<8&HyC*Y4nl_hvcSY;mCuncSRz%6O3BKpBoR|VhkXI{v zu9lqZR5Q)lI^eSp*CQnKt>F7uf76_k!9fqpq4(XHQ=opj{dQsNwZGy`4P;j6VAo^H z2bdyQi6s9MDV&y;#DAKP!v!(tpuH9~_-3)Hq;49j+&`;z*h%X5tnZoIcB&pi{+C3fS;u?iF_!CcvC5!c_D*Z*KsC8vxs? zi_Z-)`T-pP>q~yf)q%d%At|6n{eQ1)INTa|gD2uV&cHq#iW2QxO!hQPa_{ zImqdddm;DHdITv!BuB@p)kRC*qAPtr9T#mW(|@2>G!XgUDbW*(964i?TXAM9ct$rD zv_|0WmVw&VWNlbxMjpLlUayUD{bsrgD${8hy$f>wSU*iNM@F7h=%h)fNATh6;ykO) zaW({{+?VUWVFv7UWQ*dSoEKbZ+}_yEq1T)I&P(UUOkaB(dre}rBE0Z zCF$}qg(WA==-g8E;oBN-Ku&93siMN2b{RC+05iL=QDcuO}(Y=rEs-?ls#yi>5 ztp1=<9!*x$W7OwjV$J|KUp58~M){?w8}acWRqz#(=81?}8n(x(HL{>Vuv}IXh0A4X z+Km5se6$v8aLEFLN#ph&LCE7rUee9fA>PzvVfOQxd5^4H z_=Dl?(RR7ZxqK?vXQcB{wX;#v^ks)Qqb3!(3f=vyDm%rjMaY$X73g?1BWZ<1@LtAO zq;YNx6jLkLBX-;03Wt0Gx+JAG*r=&oB(Z%0(?@-Uj}#vV<}Y^901hbOB7rBNSWB03 zh5` zipJM}7xS|&sfK;J22`7JnH29{u}S?imxD_x_t3wzJRkQatg6yM?50EgVZv#WlqbBG@v0JVOqJFHQXf_mc6N#Q}EJ>K1AIDoz_cI*iH5TA{u_=bvs0v-yMuaI7Tq1U*ss~Xnf=QsY z2%w$~5ek0lcL~t)C%BZm90Zwj3@YlE5xAZK{7wY36sEcEE^f4jvZX&6)Xo&5^BvVQ zJzO}yH1SF?Re`QDD7@V|enU0srHvoAqs6U7q$1zBzQBJLmb_m%F96rQ0RrHA1U*@t zdd~hyb9-HDbNzH95Q$yU({I5jY2Jw!X>Kj{2>eYXZNn_;jM|1w;~xzB_+OfOKL^k4 zdlF^hS)W5avG@+h<~DBkQ01!EfC&4^ab#}pGki2z;98_KkDtp(=%A{H>6v+RT1?5v U{atk~U!(bmt@B|f=Jcii0cPYbWdHyG literal 0 HcmV?d00001 diff --git a/docs/_static/FlashInfer-white-background.png b/docs/_static/FlashInfer-white-background.png new file mode 100644 index 0000000000000000000000000000000000000000..d0936895cc121cc2c63444bf5e50d8d09ea5064b GIT binary patch literal 101505 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 z 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 QDx3SywkK^U*5|MNKTogA{Qv*} literal 0 HcmV?d00001 diff --git a/docs/api/python/cascade.rst b/docs/api/python/cascade.rst new file mode 100644 index 00000000..dd095a6c --- /dev/null +++ b/docs/api/python/cascade.rst @@ -0,0 +1,38 @@ +.. _apicascade: + +flashinfer.cascade +================== + +.. currentmodule:: flashinfer.cascade + +.. _api-merge-states: + +Merge Attention States +---------------------- + +.. autosummary:: + :toctree: ../../generated + + merge_state + merge_state_in_place + merge_states + +.. _api-cascade-attention: + +Cascade Attention +----------------- + +.. autosummary:: + :toctree: ../../generated + + batch_decode_with_shared_prefix_padded_kv_cache + + +Cascade Attention Wrapper Classes +--------------------------------- + +.. autoclass:: BatchDecodeWithSharedPrefixPagedKVCacheWrapper + :members: + +.. autoclass:: BatchPrefillWithSharedPrefixPagedKVCacheWrapper + :members: diff --git a/docs/api/python/decode.rst b/docs/api/python/decode.rst new file mode 100644 index 00000000..ca972664 --- /dev/null +++ b/docs/api/python/decode.rst @@ -0,0 +1,26 @@ +.. _apidecode: + +flashinfer.decode +================= + +.. currentmodule:: flashinfer.decode + +Single Request Decoding +----------------------- + +.. autosummary:: + :toctree: ../../generated + + single_decode_with_kv_cache + +Batch Decoding +-------------- + +.. autosummary:: + :toctree: ../../generated + + batch_decode_with_padded_kv_cache + batch_decode_with_padded_kv_cache_return_lse + +.. autoclass:: BatchDecodeWithPagedKVCacheWrapper + :members: diff --git a/docs/api/python/page.rst b/docs/api/python/page.rst new file mode 100644 index 00000000..66e64f68 --- /dev/null +++ b/docs/api/python/page.rst @@ -0,0 +1,16 @@ +.. _apipage: + +flashinfer.page +=============== + +Kernels to manipulte paged kv-cache. + +.. currentmodule:: flashinfer.page + +Append new K/V tensors to Paged KV-Cache +---------------------------------------- + +.. autosummary:: + :toctree: ../../generated + + append_paged_kv_cache diff --git a/docs/api/python/prefill.rst b/docs/api/python/prefill.rst new file mode 100644 index 00000000..9f50f195 --- /dev/null +++ b/docs/api/python/prefill.rst @@ -0,0 +1,27 @@ +.. _apiprefill: + +flashinfer.prefill +================== + +Attention kernels for prefill & append attention in both single request and batch serving setting. + +.. currentmodule:: flashinfer.prefill + +Single Request Prefill/Append Attention +--------------------------------------- + +.. autosummary:: + :toctree: ../../generated + + single_prefill_with_kv_cache + single_prefill_with_kv_cache_return_lse + +Batch Prefill/Append Attention +------------------------------ + +.. autoclass:: BatchPrefillWithPagedKVCacheWrapper + :members: + +.. autoclass:: BatchPrefillWithRaggedKVCacheWrapper + :members: + \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 534fc4e3..55345c89 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,7 +1,7 @@ import os import sys -import tlcpack_sphinx_addon +# import tlcpack_sphinx_addon # Configuration file for the Sphinx documentation builder. # # For the full list of built-in configuration values, see the documentation: @@ -10,6 +10,10 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information +sys.path.insert(0, os.path.abspath("../python")) +os.environ["BUILD_DOC"] = "1" +autodoc_mock_imports = ["torch"] + project = 'FlashInfer' author = "FlashInfer Contributors" footer_copyright = '2023-2024, {}'.format(author) @@ -22,11 +26,10 @@ extensions = [ "sphinx_tabs.tabs", - "sphinx_toolbox.collapse", - "sphinxcontrib.httpdomain", "sphinx.ext.autodoc", "sphinx.ext.napoleon", - "sphinx_reredirects", + "sphinx.ext.autosummary", + "sphinx.ext.mathjax", ] source_suffix = [".rst"] @@ -44,11 +47,7 @@ # -- Options for HTML output ---------------------------------------------- -# The theme is set by the make target -import sphinx_rtd_theme - -html_theme = "sphinx_rtd_theme" -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +html_theme = "furo" #"sphinx_rtd_theme" templates_path = [] @@ -60,27 +59,8 @@ "logo_only": True, } -header_links = [ - ("Home", "https://flashinfer.ai"), - ("Github", "https://github.com/flashinfer-ai/flashinfer"), - ("Discussions", "https://github.com/orgs/flashinfer-ai/discussions"), -] - -html_context = { - "footer_copyright": footer_copyright, - "footer_note": footer_note, - "header_links": header_links, - "display_github": True, - "github_user": "flashinfer-ai", - "github_repo": "flashinfer", - "github_version": "main/docs/", - "theme_vcs_pageview_mode": "edit", - # "header_logo": "/path/to/logo", - # "header_logo_link": "", - # "version_selecter": "", +html_static_path = ["_static"] +html_theme_options = { + "light_logo": "FlashInfer-white-background.png", + "dark_logo": "FlashInfer-black-background.png", } - -# add additional overrides -templates_path += [tlcpack_sphinx_addon.get_templates_path()] -html_static_path += [tlcpack_sphinx_addon.get_static_path()] - diff --git a/docs/index.rst b/docs/index.rst index 3a23a81a..d171a797 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,15 +6,29 @@ Welcome to FlashInfer's documentation! ====================================== +`Blog `_ | `Discussion Forum `_ | `GitHub `_ + +FlashInfer is a library for Language Languages Models that provides high-performance implementation of LLM GPU kernels such as FlashAttention, PageAttention and LoRA. FlashInfer focus on LLM serving and inference, and delivers state-the-art performance across diverse scenarios. + .. toctree:: :maxdepth: 2 - :caption: Contents: + :caption: Get Started + installation +.. toctree:: + :maxdepth: 2 + :caption: Tutorials -Indices and tables -================== + tutorials/recursive_attention + tutorials/kv_layout + +.. toctree:: + :maxdepth: 2 + :caption: PyTorch API Reference -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` + api/python/decode + api/python/prefill + api/python/cascade + api/python/page + \ No newline at end of file diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 00000000..3ad79832 --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,47 @@ +.. _installation: + +Installation +============ + +Python Package +-------------- +FlashInfer is available as a Python package, built on top of `PyTorch `_ to +easily integrate with your python applications. + +Prerequisites +^^^^^^^^^^^^^ + +- OS: Linux only +- Python: 3.10, 3.11 +- PyTorch CUDA 11.8/12.1 + - Use ``python -c "import torch; print(torch.version.cuda)"`` to check your PyTorch CUDA version. +- Supported GPU architectures: sm_80, sm_86, sm_89, sm_90 (sm_75 support is working in progress). + +Quick Start +^^^^^^^^^^^ + +.. tabs:: + .. tab:: PyTorch CUDA 11.8 + + .. code-block:: bash + + pip install flashinfer -i https://flashinfer.ai/whl/cu118/ + + .. tab:: PyTorch CUDA 12.1 + + .. code-block:: bash + + pip install flashinfer -i https://flashinfer.ai/whl/cu121/ + + +C++ API +------- + +FlashInfer is a header-only library with only CUDA/C++ standard library dependency +that can be directly integrated into your C++ project without installation. + +You can check our `unittest and benchmarks `_ on how to use our C++ APIs at the moment. + +.. note:: + The ``nvbench`` and ``googletest`` dependency in ``3rdparty`` directory are only + used to compile unittests and benchmarks, and are not required for the library itself. diff --git a/docs/requirements.txt b/docs/requirements.txt index 0604736c..7717b04c 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,9 +1,7 @@ sphinx-tabs == 3.4.1 -sphinx-rtd-theme -sphinx == 5.2.3 +sphinx == 7.2.6 sphinx-toolbox == 3.4.0 -tlcpack-sphinx-addon==0.2.2 -sphinxcontrib_httpdomain==1.8.1 -sphinxcontrib-napoleon==0.7 -sphinx-reredirects==0.1.2 - +sphinxcontrib_httpdomain == 1.8.1 +sphinxcontrib-napoleon == 0.7 +sphinx-reredirects == 0.1.2 +furo == 2024.01.29 diff --git a/docs/tutorials/kv_layout.rst b/docs/tutorials/kv_layout.rst new file mode 100644 index 00000000..8ee06282 --- /dev/null +++ b/docs/tutorials/kv_layout.rst @@ -0,0 +1,98 @@ +.. _kv-layout: + +KV-Cache Layout in FlashInfer +============================= + +Layout: NHD/HND +--------------- + +FlashInfer provides two layouts for last 3 dimensions in KV-Cache: ``NHD`` and ``HND``: + +- ``NHD``: the last 3 dimensions are organized as ``(seq_len, num_heads, head_dim)``. +- ``HND``: the last 3 dimensions are organized as ``(num_heads, head_dim, seq_len)``. + +The ``NHD`` layout is more natural because it's consistent with the output of +:math:`xW_k` and :math:`xW_v` without transpose. The ``HND`` layout is more friendly +for GPU implementation when KV-Cache uses low-precision data type (e.g. fp8). +In practice we don't observe significant performance difference between these two layouts +on fp16 kV-Cache and we prioritize ``NHD`` layout for better readability. FlashInfer implements +Attention kernels on both layouts and we provide an option to select between them (``NHD`` +by default). + +.. _ragged-layout: + +Ragged Tensor +------------- + +In batched inference/serving, the input sequence length may vary across different samples. +When there is no need to change the sequence length (e.g. in prefilling stage), we can use ``RaggedTensor`` to store +the key/value tensors in KV-Cache: + +.. image:: https://raw.githubusercontent.com/flashinfer-ai/web-data/main/tutorials/ragged.png + :width: 400 + :align: center + :alt: Data structure of Ragged KV-Cache. + +The keys (or values) of all requests are packed into a single ``data`` tensor without padding, +we use a ``indptr`` array (``num_requests+1`` elements, the first element is always zero) +to store the information of variable sequence lengths of each request +(``indptr[i+1]-indptr[i]`` is the sequence length of request ``i``), the ``data`` tensor has +shape ``(indptr[-1], num_heads, head_dim)`` when the layout is ``NHD``. + +We can use ``data[indptr[i]:indptr[i+1]]`` to slice the keys (or values) of request ``i``. + +.. _page-layout: + +FlashInfer APIs +~~~~~~~~~~~~~~~ + +FlashInfer provides :class:`flashinfer.prefill.BatchPrefillWithRaggedKVCacheWrapper` to compute +the prefill attention between queries stored in ragged tensor and keys/values stored in ragged +KV-Cache. + +Page Table +---------- + +When KV-Cache is dynamic (e.g. in append or decode stage), packing all keys/values is not +efficient because the sequence length per request changes over time. `vLLM `_ +proposes to organize KV-Cache as a Page Table. In FlashInfer, we treat the page-table as +a block sparse matrix (each used page can be viewed as an non-zero block in block sparse matrix) +and uses the `CSR format `_ +to index the pages in KV-Cache. + +.. image:: https://raw.githubusercontent.com/flashinfer-ai/web-data/main/tutorials/page_layout.png + :width: 800 + :align: center + :alt: Data structure of Paged KV-Cache. + +For each request, we keep an record of its ``page_indices``, ``last_page_length``. +The overall ``kv_indptr`` array (with length ``num_requests+1``) can be computed as: +``[0, len(page_indices[0]), len(page_indices[0])+len(page_indices[1]), ...]``. +The overall ``kv_page_indices`` array (with length ``kv_indptr[-1]``) is the concatenation of all requests' ``page_indices``. +The overall ``last_page_lens`` array (with length ``num_requests``) is the concatenation of all requests' ``last_page_length``. + +The ``kv_data`` tensor is a 5-D tensor with shape (in ``NHD`` layout): + +.. code:: + + (max_num_pages, 2, page_size, num_heads, head_dim) + +where ``max_num_pages`` is the maximum number of pages used by all requests, ``page_size`` is the number of tokens +we fit into each page. ``2`` is the number of slots in each page (first one for keys, the second one for values). + +FlashInfer APIs +~~~~~~~~~~~~~~~ + +:meth:`flashinfer.page.append_paged_kv_cache` can append a batch of keys/values (stored as ragged tensors) to the paged KV-Cache +(the pages for these appended keys/values must be allocated prior to calling this API). + +:class:`BatchDecodeWithPagedKVCacheWrapper` and :class:`BatchPrefillWithPagedKVCacheWrapper` implements the decode attention +and prefill/append attention between queries stored in ragged tensors and keys/values stored in paged KV-Cache. + +FAQ +^^^ + +How do FlashInfer manages KV-Cache? + FlashInfer itself is not responsible for managing the page-table (pop and allocate new pages, etc.) and we leave the strategy + to the user: different serving engine might have different strategies to manage the page-table. FlashInfer is only responsible + for computing the attention between queries and keys/values stored in KV-Cache. diff --git a/docs/tutorials/recursive_attention.rst b/docs/tutorials/recursive_attention.rst new file mode 100644 index 00000000..702d306e --- /dev/null +++ b/docs/tutorials/recursive_attention.rst @@ -0,0 +1,80 @@ +.. _recursive-attention: + +Attention States and Recursive form of Self-Attention +===================================================== + + +FlashInfer introduces the concept of **attention states**, which fully characterizes +the attention between a query and a set of key/value pairs. We further defines a +**merge** operator on the **attention states**. This merge operator facilitates the +computation of complete attention by allowing the recursive merging of attention states. + +Suppose we define :math:`s_i = \mathbf{q}\mathbf{k}_i^T` as the pre-softmax attention +score between the query :math:`\mathbf{q}` and the key :math:`\mathbf{k}_i`. The Self-Attention +score on index :math:`i` can be generalized to index set :math:`I`: + +.. math:: + + s(I)=\log\left(\sum_{i\in I}\exp\left(s_i\right)\right) + +We can also generalize the value on index :math:`i` to index set :math:`I`: + +.. math:: + + \mathbf{v}(I)=\frac{\sum_{i\in I}\exp\left(s_i\right)\mathbf{v}_i}{\exp(s(I))} + +The *attention state* of the index set :math:`i` can be defined as a tuple :math:`(s(I), \mathbf{v}(I))`. + +Then we can define the **merge** operator :math:`\oplus` of two attention states as: + +.. math:: + + \begin{bmatrix}\mathbf{v}(I\cup J)\\s(I\cup J)\end{bmatrix}=\begin{bmatrix}\mathbf{v}(I)\\s(I)\end{bmatrix}\oplus\begin{bmatrix}\mathbf{v}(J)\\s(J)\end{bmatrix}=\begin{bmatrix} \frac{\mathbf{v}(I)\exp(s(I)) + \mathbf{v}(J)\exp(s(J))}{\exp(s(I)) + \exp(s(J))} \\ \log(\exp(s(I)) + \exp(s(J))) \end{bmatrix} + +The **attention state** on the entire sequence can be defined as: + +.. math:: + + \begin{bmatrix}\mathbf{v}(\{1,2,\dots, n\})\\s(\{1,2,\dots, n\})\end{bmatrix} = \bigoplus_{i=1}^{n} \begin{bmatrix}\mathbf{v}_i\\s_i\end{bmatrix} + +Then $\mathbf{v}(\{1,2,\dots, n\})$ is the final attention output. + +.. note:: + + The generalized score :math:`s` is also known as log-sum-exp (``lse`` for short). + +Applications +------------ + +Note that :math:`\oplus` operator is **commutative** and **associative**, which means we can +safely offload the self-attention computation on a subset of KV to different devices +and **merge** the results **in any order**. + +There are several interesting applications of this recursive form of self-attention in FlashInfer so far: + +Shared-Prefix Batch Decoding + Many LLM applications involves batch decoding with the shared long prompt, FlashInfer decomposes attention + on the entire KV-Cache to shared prefix attention and unique suffixes attention. + This decomposition enables the offloading of these components to different kernel implementations, resulting + in a remarkable 30x acceleration in scenarios with long context and large batch-size. + Such decomposition accelerates the operator by 30 times in long context setting. + Check `our blog post `_ on more details about this application, + and :ref:`api-cascade-attention` on how to use this feature in FlashInfer. + +KV Sequence Parallelism + For long context LLM inference/serving, the batch size and number of heads per GPU is limited by the GPU memory, + and the default parallelism strategy cannot use all SMs in GPUs, which results in suboptimal performance. + Inspired by `Split-K `_ trick + in GEMM optimizations. FlashInfer partitions the KV sequence dimension and dispatches the attention computations to + different thread-blocks and merge them in a second pass. This same idea was also proposed in Flash-Decoding, you can + check their great `blog post `_ for visualizations and more details. + +Related APIs +------------ + +FlashInfer exposes several APIs to facilitate the recursive attention computation: + +- :ref:`api-merge-states` defines the operators to merge attention states. +- :ref:`apiprefill` and :ref:`apidecode` defines operators that returns attention states (APIs + with suffix ``_return_lse`` returns both attention output :math:`v` and score :math:`s`). + diff --git a/python/flashinfer/cascade.py b/python/flashinfer/cascade.py index 596ce38d..1d5b8890 100644 --- a/python/flashinfer/cascade.py +++ b/python/flashinfer/cascade.py @@ -15,10 +15,20 @@ """ import math from typing import Optional - import torch -from . import _kernels +try: + from . import _kernels +except ImportError as e: + import os + import logging + + if os.environ.get("BUILD_DOC", "0") == "1": + _kernels = None + logging.warning("Kernels are not loaded in documentation build mode.") + else: + raise e + from .decode import ( batch_decode_with_padded_kv_cache_return_lse, BatchDecodeWithPagedKVCacheWrapper, @@ -39,31 +49,33 @@ def merge_state( v_a: torch.Tensor, s_a: torch.Tensor, v_b: torch.Tensor, s_b: torch.Tensor ): - r"""Merge the attention output (V) and the logsumexp value (S) from the two KV-segments. + r"""Merge the attention output ``V`` and the logsumexp value ``S`` from the two + KV-segments. + Check :ref:`our tutorial ` on the mathematical details. Parameters ---------- v_a : torch.Tensor - The attention output from the KV segment A. - Shape: [seq_len, num_heads, head_dim] + The attention output from the KV segment ``A``, shape: + ``[seq_len, num_heads, head_dim]``. s_a : torch.Tensor - The logsumexp value from the KV segment A. Expected to be a float32 tensor. - Shape: [seq_len, num_heads] + The logsumexp value from the KV segment ``A``. expected to be a float32 tensor, + shape: ``[seq_len, num_heads]``. v_b : torch.Tensor - The attention output from the KV segment B. - Shape: [seq_len, num_heads, head_dim] + The attention output from the KV segment ``B``, + shape: ``[seq_len, num_heads, head_dim]``. s_b : torch.Tensor - The logsumexp value from the KV segment B. Expected to be a float32 tensor. - Shape: [seq_len, num_heads] + The logsumexp value from the KV segment ``B``, expected to be a float32 tensor, + shape: ``[seq_len, num_heads]`` Returns ------- V : torch.Tensor - The merged attention output (equivalent to attention with merged KV-segment [A: B]). - Shape: [batch_size, num_heads, head_dim] + The merged attention output (equivalent to attention with merged KV-segment + ``[A: B]``), shape: ``[batch_size, num_heads, head_dim]``. S : torch.Tensor - The logsumexp value from the merged KV-segment [A: B]. - Shape: [batch_size, num_heads] + The logsumexp value from the merged KV-segment ``[A: B]``, shape: + ``[batch_size, num_heads]``. """ return _kernels.merge_state(v_a, s_a, v_b, s_b) @@ -71,46 +83,48 @@ def merge_state( def merge_state_in_place( v: torch.Tensor, s: torch.Tensor, v_other: torch.Tensor, s_other: torch.Tensor ): - r"""Merge the self-attention state (v, s) with another state (v_other, s_other) in-place. + r"""Merge the self-attention state ``(v, s)`` with another state + ``(v_other, s_other)`` in-place. Parameters ---------- v : torch.Tensor - The partial v to be updated in-place. - Shape: (seq_len, num_heads, head_dim) + The partial attention output to be updated in-place, shape: + ``(seq_len, num_heads, head_dim)``. s : torch.Tensor - The partial logsumexpr value to be updated in-place, expected to be a float32 tensor. - Shape: (seq_len, num_heads) + The partial logsumexpr value to be updated in-place, expected to be a float32 + tensor, shape: ``(seq_len, num_heads)``. v_other : torch.Tensor - The other v to be merged. - Shape: (seq_len, num_heads, head_dim) + The other attention output to be merged, shape: + ``(seq_len, num_heads, head_dim)``. s_other : torch.Tensor - The other logsumexp value to be merged, expected to be a float32 tensor. - Shape: (seq_len, num_heads) + The other logsumexp value to be merged, expected to be a float32 tensor, + shape: ``(seq_len, num_heads)``. """ _kernels.merge_state_in_place(v, s, v_other, s_other) def merge_states(v: torch.Tensor, s: torch.Tensor): - r"""Merge the attention output (V) and the logsumexp value (S) from multiple KV-segments. + r"""Merge the attention output ``V`` and the logsumexp value ``S`` from multiple + KV-segments. Parameters ---------- v : torch.Tensor - The attention output from the KV segments. - Shape: [seq_len, num_kv_segments, num_heads, head_dim] + The attention output from the KV segments, shape: + ``[seq_len, num_kv_segments, num_heads, head_dim]``. s : torch.Tensor - The logsumexp value from the KV segments. - Shape: [seq_len, num_kv_segments, num_heads] + The logsumexp value from the KV segments, shape: + ``[seq_len, num_kv_segments, num_heads]``, expected + to be a float32 tensor. Returns ------- V : torch.Tensor - The merged attention output. - Shape: [seq_len, num_heads, head_dim] + The merged attention output, shape: ``[seq_len, num_heads, head_dim]``. S : torch.Tensor - The logsumexp value from the merged KV-segments. - Shape: [seq_len, num_heads] + The logsumexp value from the merged KV-segments, shape: + ``[seq_len, num_heads]``. """ return _kernels.merge_states(v, s) @@ -127,40 +141,49 @@ def batch_decode_with_shared_prefix_padded_kv_cache( rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): - r"""Batch decode with shared prefix padded KV cache. + r"""Decode attention between queries and shared prefix kv-cache for batch of + requests. Parameters ---------- q : torch.Tensor - Shape: [batch_size, num_qo_heads, head_dim] + The query tensor, shape: ``[batch_size, num_qo_heads, head_dim]``. k_shared : torch.Tensor - Shape: [shared_prefix_len, num_kv_heads, head_dim] if NHD - [num_kv_heads, shared_prefix_len, head_dim] if HND + The shared prefix key tensor, shape: + ``[shared_prefix_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` is ``NHD``, + or ``[num_kv_heads, shared_prefix_len, head_dim]`` if :attr:`kv_layout` is + ``HND``. v_shared : torch.Tensor - Shape: [shared_prefix_len, num_kv_heads, head_dim] if NHD - [num_kv_heads, shared_prefix_len, head_dim] if HND + The shared prefix value tensor, shape: + ``[shared_prefix_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` is ``NHD``, + or ``[num_kv_heads, shared_prefix_len, head_dim]`` if :attr:`kv_layout` is + ``HND``. k_unique : torch.Tensor - Shape: [batch_size, unique_len, num_kv_heads, head_dim] if NHD - [batch_size, num_kv_heads, unique_len, head_dim] if HND + The request-independent suffix key tensor, shape: + ``[batch_size, unique_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` is + ``NHD``, or ``[batch_size, num_kv_heads, unique_len, head_dim]`` if + :attr:`kv_layout` is ``HND``. v_unique : torch.Tensor - Shape: [batch_size, unique_len, num_kv_heads, head_dim] if NHD - [batch_size, num_kv_heads, unique_len, head_dim] if HND + The request-independent suffix value tensor, shape: + ``[batch_size, unique_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` is + ``NHD``, or ``[batch_size, num_kv_heads, unique_len, head_dim]`` if + :attr:`kv_layout` is ``HND``. kv_layout : str - The layout of the input k/v tensors, could be either "NHD" or "HND". + The layout of the kv-cache, could be either "NHD" or "HND". allow_fp16_qk_reduction : bool - Whether to use f16 for qk reduction (could be significantly faster for GeForce cards, at - the cost of slight precision loss). + Whether to use f16 for qk reduction (faster at the cost of slight precision + loss). sm_scale : Optional[float] - The scale of softmax, if not provided, will be set to 1 / sqrt(head_dim) + The scale of softmax, if not provided, will be set to ``1 / sqrt(head_dim)`` rope_scale : Optional[float] - The scale used in RoPE interpolation, if not provided, will be set to 1.0. + The scale used in RoPE interpolation, if not provided, will be set to ``1.0``. rope_theta : Optional[float] - The theta used in RoPE, if not provided, will be set to 1e4. + The theta used in RoPE, if not provided, will be set to ``1e4``. Returns ------- V : torch.Tensor - Shape: [batch_size, num_heads, head_dim] + The attention output, shape: ``[batch_size, num_heads, head_dim]`` """ check_kv_layout(kv_layout) V_shared, S_shared = single_prefill_with_kv_cache_return_lse( @@ -190,6 +213,19 @@ def batch_decode_with_shared_prefix_padded_kv_cache( class BatchDecodeWithSharedPrefixPagedKVCacheWrapper: + r"""Wrapper class for decode attention with shared-prefix paged kv-cache for batch + of requests. + + Check :ref:`our tutorial` for page table layout. + + Note + ---- + To accelerate computation, FlashInfer's shared prefix batch decode attention creates + some auxiliary data structures, these data structures can be reused across multiple + batch decode attention calls (e.g. different Transformer layers). This wrapper class + manages the lifecycle of these data structures. + """ + def __init__(self, workspace_buffer: torch.Tensor, kv_layout: str = "NHD"): self._batch_decode_wrapper = BatchDecodeWithPagedKVCacheWrapper( workspace_buffer, kv_layout @@ -197,6 +233,14 @@ def __init__(self, workspace_buffer: torch.Tensor, kv_layout: str = "NHD"): self._kv_layout = kv_layout def reset_workspace_buffer(self, new_workspace_buffer: torch.Tensor): + r"""Reset the workspace buffer. + + Parameters + ---------- + new_workspace_buffer : torch.Tensor + The new workspace buffer, the device of the new workspace buffer should + be the same as the device of the input tensors. + """ self._batch_decode_wrapper.reset_workspace_buffer(new_workspace_buffer) def begin_forward( @@ -210,6 +254,43 @@ def begin_forward( page_size: int, data_type: str = "float16", ): + r"""Create auxiliary data structures for shared-prefix batch decode for multiple + forward calls within the same decode step. + + Parameters + ---------- + indptr : torch.Tensor + The indptr of the paged kv cache, shape: ``[batch_size + 1]`` + indices : torch.Tensor + The page indices of the paged kv cache, shape: ``[qo_indptr[-1]]`` + last_page_len : torch.Tensor + The number of entries in the last page of each request in the paged kv + cache, shape: ``[batch_size]`` + num_qo_heads : int + The number of query/output heads + num_kv_heads : int + The number of key/value heads + head_dim : int + The dimension of the heads + page_size : int + The page size of the paged kv cache + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). + data_type : Union[str, torch.dtype] + The data type of the paged kv cache + + Note + ---- + The :meth:`begin_forward` method should be called before any :meth:`forward` or + :meth:`forward_return_lse` calls, + auxiliary data structures will be created during this call and cached for + multiple forward calls. + + The ``num_qo_heads`` must be a multiple of ``num_kv_heads``. If ``num_qo_heads`` + is not equal to ``num_kv_heads``, the function will use + `grouped query attention `_. + """ self._batch_decode_wrapper.begin_forward( unique_kv_indptr, unique_kv_indices, @@ -223,6 +304,7 @@ def begin_forward( ) def end_forward(self): + r"""Clear auxiliary data structures created by :meth:`begin_forward`.""" self._batch_decode_wrapper.end_forward() def forward( @@ -235,6 +317,44 @@ def forward( rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): + r"""Compute batch decode attention between queries and shared-prefix paged + kv-cache. + + Parameters + ---------- + q : torch.Tensor + The query tensor, shape: ``[batch_size, num_qo_heads, head_dim]``. + k_shared : torch.Tensor + The shared prefix key tensor, shape: + ``[shared_prefix_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` is + ``NHD``, or ``[num_kv_heads, shared_prefix_len, head_dim]`` if + :attr:`kv_layout` is ``HND``. + v_shared : torch.Tensor + The shared prefix value tensor, shape: + ``[shared_prefix_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` is + ``NHD``, or ``[num_kv_heads, shared_prefix_len, head_dim]`` if + :attr:`kv_layout` is ``HND``. + unique_kv_data : torch.Tensor + A 5-D tensor of paged kv-cache data storing the request-independent suffix + key and value tensors, shape: + ``[max_num_pages, 2, page_size, num_kv_heads, head_dim]`` if + :attr:`kv_layout` is ``NHD``, or + ``[max_num_pages, 2, page_size, num_kv_heads, head_dim]`` if + :attr:`kv_layout` is ``HND``. + allow_fp16_qk_reduction : bool + Whether to use f16 for qk reduction (faster at the cost of slight precision + loss). + rope_scale : Optional[float] + The scale used in RoPE interpolation, if not provided, will be set to + ``1.0``. + rope_theta : Optional[float] + The theta used in RoPE, if not provided, will be set to ``1e4``. + + Returns + ------- + V : torch.Tensor + The attention output, shape: ``[batch_size, num_heads, head_dim]`` + """ V_shared, S_shared = single_prefill_with_kv_cache_return_lse( q, k_shared, @@ -258,13 +378,45 @@ def forward( class BatchPrefillWithSharedPrefixPagedKVCacheWrapper: + r"""Wrapper class for prefill/append attention with shared-prefix paged kv-cache for + batch of requests. + + Check :ref:`our tutorial` for paged kv-cache layout. + + Note + ---- + To accelerate computation, FlashInfer's shared-prefix batch prefill/append attention + operators creates some auxiliary data structures, these data structures can be + reused across multiple prefill/append attention calls (e.g. different Transformer + layers). This wrapper class manages the lifecycle of these data structures. + """ + def __init__(self, workspace_buffer: torch.Tensor, kv_layout: str = "NHD"): + r"""Constructor of :class:`BatchDecodeWithSharedPrefixPagedKVCacheWrapper`. + + Parameters + ---------- + workspace_buffer : torch.Tensor + The user reserved workspace buffer used to store auxiliary data structures, + recommended size is 16MB, the device of the workspace buffer should be the + same as the device of the input tensors. + kv_layout : str + The layout of the input k/v tensors, could be either ``NHD`` or ``HND``. + """ self._batch_prefill_wrapper = BatchPrefillWithPagedKVCacheWrapper( workspace_buffer, kv_layout ) self._kv_layout = kv_layout def reset_workspace_buffer(self, new_workspace_buffer: torch.Tensor): + r"""Reset the workspace buffer. + + Parameters + ---------- + new_workspace_buffer : torch.Tensor + The new workspace buffer, the device of the new workspace buffer should + be the same as the device of the input tensors. + """ self._batch_prefill_wrapper.reset_workspace_buffer(new_workspace_buffer) def begin_forward( @@ -276,6 +428,36 @@ def begin_forward( num_qo_heads: int, num_kv_heads: int, ): + r"""Create auxiliary data structures for shared-prefix batch prefill/append + attention for multiple forward calls within the same prefill/append step. + + Parameters + ---------- + qo_indptr : torch.Tensor + The indptr of the query/output tensor, shape: ``[batch_size + 1]``. + paged_kv_indptr : torch.Tensor + The indptr of the paged kv-cache, shape: ``[batch_size + 1]``. + paged_kv_indices : torch.Tensor + The page indices of the paged kv-cache, shape: ``[qo_indptr[-1]]``. + paged_kv_last_page_len : torch.Tensor + The number of entries in the last page of each request in the paged + kv-cache, shape: ``[batch_size]``. + num_qo_heads : int + The number of query/output heads. + num_kv_heads : int + The number of key/value heads. + + Notes + ----- + The :meth:`begin_forward` method should be called before any :meth:`forward` + or :meth:`forward_return_lse` calls, auxiliary data structures will be created + during this call and cached for multiple forward calls. + + The ``num_qo_heads`` must be a multiple of ``num_kv_heads``. If ``num_qo_heads`` + is not equal to ``num_kv_heads``, the function will use + `grouped query attention `_. + """ + self._batch_prefill_wrapper.begin_forward( qo_indptr, paged_kv_indptr, @@ -286,6 +468,7 @@ def begin_forward( ) def end_forward(self): + r"""Clear the auxiliary data structures created by :meth:`begin_forward`.""" self._batch_prefill_wrapper.end_forward() def forward( @@ -299,6 +482,46 @@ def forward( rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): + r"""Compute batch prefill/append attention between query and shared-prefix paged + kv-cache. + + Parameters + ---------- + q : torch.Tensor + The query tensor, shape: ``[qo_indptr[-1], num_qo_heads, head_dim]``. + k_shared : torch.Tensor + The shared prefix key tensor, shape: + ``[shared_prefix_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` is + ``NHD``, or ``[num_kv_heads, shared_prefix_len, head_dim]`` if + :attr:`kv_layout` is ``HND``. + v_shared ; torch.Tensor + The shared prefix value tensor, shape: + ``[shared_prefix_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` is + ``NHD``, or ``[num_kv_heads, shared_prefix_len, head_dim]`` if + :attr:`kv_layout` is ``HND``. + unique_kv_data : torch.Tensor + A 5-D tensor of paged kv-cache data storing the request-independent suffix + key and value tensors, shape: + ``[max_num_pages, 2, page_size, num_kv_heads, head_dim]`` if + :attr:`kv_layout` is ``NHD``, or + ``[max_num_pages, 2, page_size, num_kv_heads, head_dim]`` if + :attr:`kv_layout` is ``HND``. + causal : bool + Whether to apply causal mask on the attention matrix. + allow_fp16_qk_reduction : bool + Whether to use f16 for qk reduction (faster at the cost of slight precision + loss). + rope_scale : Optional[float] + The scale used in RoPE interpolation, if not provided, will be set to + ``1.0``. + rope_theta : Optional[float] + The theta used in RoPE, if not provided, will be set to ``1e4``. + + Returns + ------- + V : torch.Tensor + The attention output, shape: ``[qo_indptr[-1], num_heads, head_dim]``. + """ V_shared, S_shared = single_prefill_with_kv_cache_return_lse( q, k_shared, diff --git a/python/flashinfer/decode.py b/python/flashinfer/decode.py index b2014a2c..d4f42cc7 100644 --- a/python/flashinfer/decode.py +++ b/python/flashinfer/decode.py @@ -15,10 +15,21 @@ """ import math from typing import Optional, Union - import torch -from . import _kernels +try: + from . import _kernels +except ImportError as e: + import os + import logging + + if os.environ.get("BUILD_DOC", "0") == "1": + _kernels = None + logging.warning("Kernels are not loaded in documentation build mode.") + else: + raise e + + from .utils import ( RotaryMode, TensorLayout, @@ -43,35 +54,64 @@ def single_decode_with_kv_cache( q: torch.Tensor, k: torch.Tensor, v: torch.Tensor, - rotary_mode: str = "NONE", kv_layout: str = "NHD", + rotary_mode: str = "NONE", sm_scale: Optional[float] = None, rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): - r"""Single request decode with KV cache. + r"""Decode attention with KV Cache for single request, return attention output. Parameters ---------- q : torch.Tensor - Shape: [num_qo_heads, head_dim] + The query tensor, shape: ``[num_qo_heads, head_dim]``. k : torch.Tensor - Shape: [kv_len, num_kv_heads, head_dim] if NHD - [num_kv_heads, kv_len, head_dim] if HND + The key tensor, shape: ``[kv_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` + is ``NHD``, or ``[num_kv_heads, kv_len, head_dim]`` if :attr:`kv_layout` is + ``HND``. v : torch.Tensor - Shape: [kv_len, num_kv_heads, head_dim] if NHD - [num_kv_heads, kv_len, head_dim] if HND - rotary_mode : str - Whether to apply rotary embeddings inside attention kernels, could be - "NONE" or "LLAMA". + The value tensor, shape: ``[kv_len, num_kv_heads, head_dim]`` if + :attr:`kv_layout` is ``NHD``, or ``[num_kv_heads, kv_len, head_dim]`` if + :attr:`kv_layout` is ``HND``. kv_layout : str - The layout of the input k/v tensors, could be either "NHD" or "HND". + The layout of the input k/v tensors, could be either ``NHD`` or ``HND``. + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). sm_scale : Optional[float] - The scale of softmax, if not provided, will be set to 1 / sqrt(head_dim) + The scale of softmax, if not provided, will be set to ``1 / sqrt(head_dim)``. rope_scale : Optional[float] - The scale used in RoPE interpolation, if not provided, will be set to 1.0. + The scale used in RoPE interpolation, if not provided, will be set to ``1.0``. rope_theta : Optional[float] - The theta used in RoPE, if not provided, will be set to 1e4. + The theta used in RoPE, if not provided, will be set to ``1e4``. + + Returns + ------- + torch.Tensor + The attention output, shape: ``[num_qo_heads, head_dim]`` + + Examples + -------- + + >>> import torch + >>> import flashinfer + >>> kv_len = 4096 + >>> num_qo_heads = 32 + >>> num_kv_heads = 32 + >>> head_dim = 128 + >>> q = torch.randn(num_qo_heads, head_dim).half().to("cuda:0") + >>> k = torch.randn(kv_len, num_kv_heads, head_dim).half().to("cuda:0") + >>> v = torch.randn(kv_len, num_kv_heads, head_dim).half().to("cuda:0") + >>> o = flashinfer.single_decode_with_kv_cache(q, k, v) + >>> o.shape + torch.Size([32, 128]) + + Notes + ----- + The ``num_qo_heads`` must be a multiple of ``num_kv_heads``. If ``num_qo_heads`` is + not equal to ``num_kv_heads``, the function will use + `grouped query attention `_. """ check_rotary_mode(rotary_mode) check_kv_layout(kv_layout) @@ -106,23 +146,45 @@ def batch_decode_with_padded_kv_cache( rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): - r"""Batch decode with padded KV cache. + r"""Decode attention with padded KV cache for batch of requests, return attention + output. Parameters ---------- q : torch.Tensor - Shape: [batch_size, num_qo_heads, head_dim] + The query tensor, shape: ``[batch_size, num_qo_heads, head_dim]``. k_padded : torch.Tensor - Shape: [batch_size, padded_seq_len, num_kv_heads, head_dim] if NHD - [batch_size, num_kv_heads, padded_seq_len, head_dim] if HND + The padded key tensor, shape: + ``[batch_size, padded_seq_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` + is ``NHD`` or ``[batch_size, num_kv_heads, padded_seq_len, head_dim]`` if + :attr:`kv_layout` is ``HND``. v_padded : torch.Tensor - Shape: [batch_size, padded_seq_len, num_kv_heads, head_dim] if NHD - [batch_size, num_kv_heads, padded_seq_len, head_dim] if HND + The padded value tensor, shape: + ``[batch_size, padded_seq_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` + is ``NHD`` or ``[batch_size, num_kv_heads, padded_seq_len, head_dim]`` if + :attr:`kv_layout` is ``HND``. + kv_layout : str + The layout of the input k/v tensors, could be either ``NHD`` or ``HND``. + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). + sm_scale : Optional[float] + The scale of softmax, if not provided, will be set to ``1 / sqrt(head_dim)``. + rope_scale : Optional[float] + The scale used in RoPE interpolation, if not provided, will be set to ``1.0``. + rope_theta : Optional[float] + The theta used in RoPE, if not provided, will be set to ``1e4``. Returns ------- - V : torch.Tensor - Shape: [batch_size, num_heads, head_dim] + torch.Tensor + The attention output, shape: ``[batch_size, num_qo_heads, head_dim]``. + + Notes + ----- + The ``num_qo_heads`` must be a multiple of ``num_kv_heads``. If ``num_qo_heads`` is + not equal to ``num_kv_heads``, the function will use + `grouped query attention `_. """ if sm_scale is None: head_dim = q.shape[-1] @@ -154,36 +216,48 @@ def batch_decode_with_padded_kv_cache_return_lse( rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): - r""" + r"""Decode attention with padded KV cache for batch of requests, return attention + output and logsumexp of attention scores, return attention output and logsumexp of + attention scores. + Parameters ---------- q : torch.Tensor - Shape: [batch_size, num_qo_heads, head_dim] + The query tensor, shape: ``[batch_size, num_qo_heads, head_dim]``. k_padded : torch.Tensor - Shape: [batch_size, padded_seq_len, num_kv_heads, head_dim] if NHD - [batch_size, num_kv_heads, padded_seq_len, head_dim] if HND + The padded key tensor, shape: + ``[batch_size, padded_seq_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` + is ``NHD`` or ``[batch_size, num_kv_heads, padded_seq_len, head_dim]`` if + :attr:`kv_layout` is ``HND``. v_padded : torch.Tensor - Shape: [batch_size, padded_seq_len, num_kv_heads, head_dim] if NHD - [batch_size, num_kv_heads, padded_seq_len, head_dim] if HND - kv_layout: str - The layout of the input k_padded/v_padded tensors, could be either - "NHD" or "HND" - rotary_mode: str - Whether to apply rotary embeddings inside attention kernels, could be - "NONE" or "LLAMA". - sm_scale: Optional[float] - The scale of softmax, if not provided, will be set to 1 / sqrt(head_dim) - rope_scale: Optional[float] - The scale used in RoPE interpolation, if not provided, will be set to 1.0. - rope_theta: Optional[float] - The theta used in RoPE, if not provided, will be set to 1e4. + The padded value tensor, shape: + ``[batch_size, padded_seq_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` + is ``NHD`` or ``[batch_size, num_kv_heads, padded_seq_len, head_dim]`` if + :attr:`kv_layout` is ``HND``. + kv_layout : str + The layout of the input k/v tensors, could be either ``NHD`` or ``HND``. + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). + sm_scale : Optional[float] + The scale of softmax, if not provided, will be set to ``1 / sqrt(head_dim)``. + rope_scale : Optional[float] + The scale used in RoPE interpolation, if not provided, will be set to ``1.0``. + rope_theta : Optional[float] + The theta used in RoPE, if not provided, will be set to ``1e4``. Returns ------- V : torch.Tensor - Shape: [batch_size, num_heads, head_dim] + The attention output, shape: [batch_size, num_qo_heads, head_dim] S : torch.Tensor - Shape: [batch_size, num_heads] + The logsumexp of attention scores, Shape: [batch_size, num_qo_heads] + + Notes + ----- + The ``num_qo_heads`` must be a multiple of ``num_kv_heads``. If ``num_qo_heads`` is + not equal to ``num_kv_heads``, the function will use + `grouped query attention `_. """ if sm_scale is None: head_dim = q.shape[-1] @@ -206,15 +280,31 @@ def batch_decode_with_padded_kv_cache_return_lse( class BatchDecodeWithPagedKVCacheWrapper: - r"""Wrapper class for batch_decode_with_paged_kv_cache kernel. + r"""Wrapper class for decode attention with paged kv-cache (first proposed in + `vLLM `_) for batch of requests. + + Check :ref:`our tutorial` for page table layout. - To accelerate computation, FlashInfer's batch decode operators creates some + Note + ---- + To accelerate computation, FlashInfer's batch decode attention creates some auxiliary data structures, these data structures can be reused across multiple - batch decode calls (e.g. different Transformer layers). This wrapper class manages - the lifecycle of these data structures. + batch decode attention calls (e.g. different Transformer layers). This wrapper class + manages the lifecycle of these data structures. """ def __init__(self, workspace_buffer: torch.Tensor, kv_layout: str = "NHD"): + r"""Constructor of :class:`BatchDecodeWithPagedKVCacheWrapper`. + + Parameters + ---------- + workspace_buffer : torch.Tensor + The user reserved workspace buffer used to store auxiliary data structures, + recommended size is 16MB, the device of the workspace buffer should be the + same as the device of the input tensors. + kv_layout : str + The layout of the input k/v tensors, could be either ``NHD`` or ``HND``. + """ check_kv_layout(kv_layout) self._kv_layout = kv_layout self._workspace_buffer = workspace_buffer @@ -226,6 +316,14 @@ def __init__(self, workspace_buffer: torch.Tensor, kv_layout: str = "NHD"): self._paged_kv_last_page_len = None def reset_workspace_buffer(self, new_workspace_buffer: torch.Tensor): + r"""Reset the workspace buffer. + + Parameters + ---------- + new_workspace_buffer : torch.Tensor + The new workspace buffer, the device of the new workspace buffer should + be the same as the device of the input tensors. + """ self._workspace_buffer = new_workspace_buffer def begin_forward( @@ -240,9 +338,41 @@ def begin_forward( rotary_mode: str = "NONE", data_type: Union[str, torch.dtype] = "float16", ): - r"""The begin_forward method should be called before any batch decode calls, - auxiliary data structures will be created during this call and cached for - multiple forward calls. + r"""Create auxiliary data structures for batch decode for multiple forward calls + within the same decode step. + + Parameters + ---------- + indptr : torch.Tensor + The indptr of the paged kv cache, shape: ``[batch_size + 1]`` + indices : torch.Tensor + The page indices of the paged kv cache, shape: ``[qo_indptr[-1]]`` + last_page_len : torch.Tensor + The number of entries in the last page of each request in the paged kv + cache, shape: ``[batch_size]`` + num_qo_heads : int + The number of query/output heads + num_kv_heads : int + The number of key/value heads + head_dim : int + The dimension of the heads + page_size : int + The page size of the paged kv cache + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). + data_type : Union[str, torch.dtype] + The data type of the paged kv cache + + Note + ---- + The :meth:`begin_forward` method should be called before any :meth:`forward` or + :meth:`forward_return_lse` calls, auxiliary data structures will be created + during this call and cached for multiple forward calls. + + The ``num_qo_heads`` must be a multiple of ``num_kv_heads``. If ``num_qo_heads`` + is not equal to ``num_kv_heads``, the function will use + `grouped query attention `_. """ self._paged_kv_indptr = indptr self._paged_kv_indices = indices @@ -270,7 +400,7 @@ def begin_forward( ) def end_forward(self): - r"""The end_forward method can clear the cached data structures.""" + r"""Clear auxiliary data structures created by :meth:`begin_forward`.""" self._paged_kv_indptr = None self._paged_kv_indices = None self._paged_kv_last_page_len = None @@ -284,6 +414,32 @@ def forward( rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): + r"""Compute batch decode attention between query and paged kv cache. + + Parameters + ---------- + q : torch.Tensor + The query tensor, shape: ``[batch_size, num_qo_heads, head_dim]`` + paged_kv_data : torch.Tensor + A 5-D tensor of the reserved paged kv-cache data, shape: + ``[max_num_pages, 2, page_size, num_kv_heads, head_dim]`` if + :attr:`kv_layout` is ``NHD``, or + ``[max_num_pages, 2, num_kv_heads, page_size, head_dim]`` if + :attr:`kv_layout` is ``HND``. + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). + rope_scale : Optional[float] + The scale used in RoPE interpolation, if not provided, will be set to + ``1.0``. + rope_theta : Optional[float] + The theta used in RoPE, if not provided, will be set to ``1e4``. + + Returns + ------- + torch.Tensor + The attention output, shape: ``[batch_size, num_qo_heads, head_dim]``. + """ check_rotary_mode(rotary_mode) if rope_scale is None: rope_scale = 1.0 @@ -310,6 +466,35 @@ def forward_return_lse( rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): + r"""Compute batch decode attention with paged kv cache, return attention output + and logsumexp of attention scores. + + Parameters + ---------- + q : torch.Tensor + The query tensor, shape: ``[batch_size, num_qo_heads, head_dim]`` + paged_kv_data : torch.Tensor + A 5-D tensor of the reserved paged kv-cache data, shape: + ``[max_num_pages, 2, page_size, num_kv_heads, head_dim]`` if + :attr:`kv_layout` is ``NHD``, or + ``[max_num_pages, 2, num_kv_heads, page_size, head_dim]`` if + :attr:`kv_layout` is ``HND``. + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). + rope_scale : Optional[float] + The scale used in RoPE interpolation, if not provided, will be set to + ``1.0``. + rope_theta : Optional[float] + The theta used in RoPE, if not provided, will be set to ``1e4``. + + Returns + ------- + V : torch.Tensor + The attention output, shape: ``[batch_size, num_qo_heads, head_dim]``. + S : torch.Tensor + The logsumexp of attention scores, Shape: ``[batch_size, num_qo_heads]``. + """ check_rotary_mode(rotary_mode) if rope_scale is None: rope_scale = 1.0 diff --git a/python/flashinfer/page.py b/python/flashinfer/page.py index 9160907e..d7944a78 100644 --- a/python/flashinfer/page.py +++ b/python/flashinfer/page.py @@ -15,8 +15,17 @@ """ import torch -from . import _kernels -from .utils import TensorLayout, check_kv_layout +try: + from . import _kernels +except ImportError as e: + import os + import logging + + if os.environ.get("BUILD_DOC", "0") == "1": + _kernels = None + logging.warning("Kernels are not loaded in documentation build mode.") + else: + raise e def append_paged_kv_cache( @@ -29,6 +38,40 @@ def append_paged_kv_cache( kv_last_page_len: torch.Tensor, kv_layout: str = "NHD", ): + r"""Append a batch of key-value pairs to a paged key-value cache. + + Parameters + ---------- + append_key : torch.Tensor + The key tensor to append in ragged tensor format, shape: + ``[append_indptr[-1], num_kv_heads, head_dim]``. + append_value : torch.Tensor + The value tensor to append in ragged tensor format, shape: + ``[append_indptr[-1], num_kv_heads, head_dim]``. + append_indptr : torch.Tensor + The indptr tensor of the key-value pairs to append, shape: ``[batch_size + 1]``. + kv_data : torch.Tensor + The 5-D tensor of the paged key-value cache, shape: + ``[max_num_pages, 2, page_size, num_kv_heads, head_dim]`` if + :attr:`kv_layout` is ``NHD``, or + ``[max_num_pages, 2, num_kv_heads, page_size, num_kv_heads]`` if + :attr:`kv_layout` is ``NHD``. + kv_indices : torch.Tensor + The page indices of the paged kv-cache, shape: ``[kv_indptr[-1]]``. + kv_indptr : torch.Tensor + The indptr of the paged kv-cache, shape: ``[batch_size + 1]``. + kv_last_page_len : torch.Tensor + The number of entries in the last page of each request in the paged kv cache, + shape: ``[batch_size]``. + kv_layout : str + The layout of the paged kv-cache, either ``NHD`` or ``HND``. + + Notes + ----- + The function assumes that the space for appended k/v have already been allocated, + which means :attr:`kv_indices`, :attr:`kv_indptr`, :attr:`kv_last_page_len` has + incorporated appended k/v. + """ check_kv_layout(kv_layout) _kernels.append_paged_kv_cache( append_key, diff --git a/python/flashinfer/prefill.py b/python/flashinfer/prefill.py index 76d2e1ac..0aaac623 100644 --- a/python/flashinfer/prefill.py +++ b/python/flashinfer/prefill.py @@ -15,10 +15,20 @@ """ import math from typing import Optional - import torch -from . import _kernels +try: + from . import _kernels +except ImportError as e: + import os + import logging + + if os.environ.get("BUILD_DOC", "0") == "1": + _kernels = None + logging.warning("Kernels are not loaded in documentation build mode.") + else: + raise e + from .utils import ( RotaryMode, TensorLayout, @@ -54,39 +64,70 @@ def single_prefill_with_kv_cache( k: torch.Tensor, v: torch.Tensor, causal: bool = False, - rotary_mode: str = "NONE", kv_layout: str = "NHD", + rotary_mode: str = "NONE", allow_fp16_qk_reduction: bool = False, rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): - r"""Single request prefill with KV cache kernel. + r"""Prefill/Append attention with KV cache for single request, return the attention + output. Parameters ---------- q : torch.Tensor - Shape: [qo_len, num_qo_heads, head_dim] if NHD - [num_qo_heads, qo_len, head_dim] if HND + The query tensor, shape: ``[qo_len, num_qo_heads, head_dim]``. k : torch.Tensor - Shape: [kv_len, num_kv_heads, head_dim] if NHD - [num_kv_heads, kv_len, head_dim] if HND + The key tensor, shape: ``[kv_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` + is ``NHD``, or ``[num_kv_heads, kv_len, head_dim]`` if :attr:`kv_layout` is + ``HND``. v : torch.Tensor - Shape: [kv_len, num_kv_heads, head_dim] if NHD - [num_kv_heads, kv_len, head_dim] if HND + The key tensor, shape: ``[kv_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` + is ``NHD``, ``[num_kv_heads, kv_len, head_dim]`` if :attr:`kv_layout` is + ``HND``. causal : bool Whether to apply causal mask to the attention matrix. - rotary_mode : str - Whether to apply rotary embeddings inside attention kernels, could be - "NONE" or "LLAMA". kv_layout : str - The layout of the input k/v tensors, could be either "NHD" or "HND". + The layout of the input k/v tensors, could be either ``NHD`` or ``HND``. + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). allow_fp16_qk_reduction : bool - Whether to use f16 for qk reduction (could be significantly faster for GeForce cards, at - the cost of precision loss). + Whether to use f16 for qk reduction (faster at the cost of slight precision + loss). rope_scale : Optional[float] The scale used in RoPE interpolation, if not provided, will be set to 1.0. rope_theta : Optional[float] The theta used in RoPE, if not provided, will be set to 1e4. + + Returns + ------- + torch.Tensor + The attention output, shape: ``[qo_len, num_qo_heads, head_dim]``. + + Examples + -------- + + >>> import torch + >>> import flashinfer + >>> qo_len = 128 + >>> kv_len = 4096 + >>> num_qo_heads = 32 + >>> num_kv_heads = 4 + >>> head_dim = 128 + >>> q = torch.randn(qo_len, num_qo_heads, head_dim).half().to("cuda:0") + >>> k = torch.randn(kv_len, num_kv_heads, head_dim).half().to("cuda:0") + >>> v = torch.randn(kv_len, num_kv_heads, head_dim).half().to("cuda:0") + >>> o = flashinfer.single_prefill_with_kv_cache(q, k, v, causal=True, + allow_fp16_qk_reduction=True) + >>> o.shape + torch.Size([128, 32, 128]) + + Notes + ----- + The ``num_qo_heads`` must be a multiple of ``num_kv_heads``. If ``num_qo_heads`` is + not equal to ``num_kv_heads``, the function will use + `grouped query attention `_. """ check_rotary_mode(rotary_mode) check_kv_layout(kv_layout) @@ -115,49 +156,73 @@ def single_prefill_with_kv_cache_return_lse( k: torch.Tensor, v: torch.Tensor, causal: bool = False, - rotary_mode: str = "NONE", kv_layout: str = "NHD", + rotary_mode: str = "NONE", allow_fp16_qk_reduction: bool = False, rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): - r"""Single request prefill with KV cache kernel, return logsumexp value. + r"""Prefill/Append attention with KV cache for single request, return attention + output and logsumexp of attention scores. Parameters ---------- q : torch.Tensor - Shape: [qo_len, num_qo_heads, head_dim] if NHD - [num_qo_heads, qo_len, head_dim] if HND + The query tensor, shape: ``[qo_len, num_qo_heads, head_dim]``. k : torch.Tensor - Shape: [kv_len, num_kv_heads, head_dim] if NHD - [num_kv_heads, kv_len, head_dim] if HND + The key tensor, shape: ``[kv_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` + is ``NHD``, or ``[num_kv_heads, kv_len, head_dim]`` if :attr:`kv_layout` is + ``HND``. v : torch.Tensor - Shape: [kv_len, num_kv_heads, head_dim] if NHD - [num_kv_heads, kv_len, head_dim] if HND + The key tensor, shape: ``[kv_len, num_kv_heads, head_dim]`` if :attr:`kv_layout` + is ``NHD``, or ``[num_kv_heads, kv_len, head_dim]`` if :attr:`kv_layout` is + ``HND``. causal : bool Whether to apply causal mask to the attention matrix. - rotary_mode : str - Whether to apply rotary embeddings inside attention kernels, could be - "NONE" or "LLAMA". kv_layout : str - The layout of the input k/v tensors, could be either "NHD" or "HND". + The layout of the input k/v tensors, could be either ``NHD`` or ``HND``. + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). allow_fp16_qk_reduction : bool - Whether to use f16 for qk reduction (could be significantly faster for GeForce cards, at - the cost of precision loss). + Whether to use f16 for qk reduction (faster at the cost of slight precision + loss). rope_scale : Optional[float] - The scale used in RoPE interpolation, if not provided, will be set to 1.0. + The scale used in RoPE interpolation, if not provided, will be set to ``1.0``. rope_theta : Optional[float] - The theta used in RoPE, if not provided, will be set to 1e4. + The theta used in RoPE, if not provided, will be set to ``1e4``. Returns ------- V : torch.Tensor - The attention output. - Shape: [qo_len, num_qo_heads, head_dim] if NHD - [num_qo_heads, qo_len, head_dim] if HND + The attention output, shape: ``[qo_len, num_qo_heads, head_dim]``. S : torch.Tensor - The logsumexp value. - Shape: [qo_len, num_qo_heads] + The logsumexp value, shape: ``[qo_len, num_qo_heads]`` + + Examples + -------- + + >>> import torch + >>> import flashinfer + >>> qo_len = 128 + >>> kv_len = 4096 + >>> num_qo_heads = 32 + >>> num_kv_heads = 4 + >>> head_dim = 128 + >>> q = torch.randn(qo_len, num_qo_heads, head_dim).half().to("cuda:0") + >>> k = torch.randn(kv_len, num_kv_heads, head_dim).half().to("cuda:0") + >>> v = torch.randn(kv_len, num_kv_heads, head_dim).half().to("cuda:0") + >>> V, S = flashinfer.single_prefill_with_kv_cache_return_lse(q, k, v, causal=True) + >>> V.shape + torch.Size([128, 32, 128]) + >>> S.shape + torch.Size([128, 32]) + + Notes + ----- + The ``num_qo_heads`` must be a multiple of ``num_kv_heads``. If ``num_qo_heads`` is + not equal to ``num_kv_heads``, the function will use + `grouped query attention `_. """ check_rotary_mode(rotary_mode) check_kv_layout(kv_layout) @@ -184,9 +249,31 @@ def single_prefill_with_kv_cache_return_lse( class BatchPrefillWithPagedKVCacheWrapper: - r"""Wrapper class of batch_prefill_with_paged_kv_cache kernel.""" + r"""Wrapper class for prefill/append attention with paged kv-cache for batch of + requests. + + Check :ref:`our tutorial` for page table layout. + + Note + ---- + To accelerate computation, FlashInfer's batch prefill/append attention operators + creates some auxiliary data structures, these data structures can be reused across + multiple prefill/append attention calls (e.g. different Transformer layers). This + wrapper class manages the lifecycle of these data structures. + """ def __init__(self, workspace_buffer: torch.Tensor, kv_layout: str = "NHD"): + r"""Constructor of :class:`BatchDecodeWithPagedKVCacheWrapper`. + + Parameters + ---------- + workspace_buffer : torch.Tensor + The user reserved workspace buffer used to store auxiliary data structures, + recommended size is 16MB, the device of the workspace buffer should be the + same as the device of the input tensors. + kv_layout : str + The layout of the input k/v tensors, could be either ``NHD`` or ``HND``. + """ check_kv_layout(kv_layout) self._kv_layout = kv_layout self._workspace_buffer = workspace_buffer @@ -199,6 +286,14 @@ def __init__(self, workspace_buffer: torch.Tensor, kv_layout: str = "NHD"): self._paged_kv_last_page_len = None def reset_workspace_buffer(self, new_workspace_buffer: torch.Tensor): + r"""Reset the workspace buffer. + + Parameters + ---------- + new_workspace_buffer : torch.Tensor + The new workspace buffer, the device of the new workspace buffer should + be the same as the device of the input tensors. + """ self._workspace_buffer = new_workspace_buffer def begin_forward( @@ -210,6 +305,35 @@ def begin_forward( num_qo_heads: int, num_kv_heads: int, ): + r"""Create auxiliary data structures for batch prefill/append attention for + multiple forward calls within the same prefill/append step. + + Parameters + ---------- + qo_indptr : torch.Tensor + The indptr of the query/output tensor, shape: ``[batch_size + 1]``. + paged_kv_indptr : torch.Tensor + The indptr of the paged kv-cache, shape: ``[batch_size + 1]``. + paged_kv_indices : torch.Tensor + The page indices of the paged kv-cache, shape: ``[qo_indptr[-1]]``. + paged_kv_last_page_len : torch.Tensor + The number of entries in the last page of each request in the paged + kv-cache, shape: ``[batch_size]``. + num_qo_heads : int + The number of query/output heads. + num_kv_heads : int + The number of key/value heads. + + Notes + ----- + The :meth:`begin_forward` method should be called before any :meth:`forward` or + :meth:`forward_return_lse` calls, auxiliary data structures will be created + during this call and cached for multiple forward calls. + + The ``num_qo_heads`` must be a multiple of ``num_kv_heads``. If ``num_qo_heads`` + is not equal to ``num_kv_heads``, the function will use + `grouped query attention `_. + """ batch_size = len(qo_indptr) - 1 self._qo_indptr = qo_indptr self._paged_kv_indptr = paged_kv_indptr @@ -220,6 +344,7 @@ def begin_forward( ) def end_forward(self): + r"""Clear the auxiliary data structures created by :meth:`begin_forward`.""" self._qo_indptr = None self._paged_kv_indptr = None self._paged_kv_indices = None @@ -236,6 +361,37 @@ def forward( rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): + r"""Compute batch prefill/append attention between query and paged kv-cache. + + Parameters + ---------- + q : torch.Tensor + The query tensor, shape: ``[qo_indptr[-1], num_qo_heads, head_dim]`` + paged_kv_data : torch.Tensor + A 5-D tensor of the reserved paged kv-cache data, shape: + ``[max_num_pages, 2, page_size, num_kv_heads, head_dim]`` + if :attr:`kv_layout` is ``NHD``, or + ``[max_num_pages, 2, num_kv_heads, page_size, head_dim]`` + if :attr:`kv_layout` is ``HND``. + causal : bool + Whether to apply causal mask to the attention matrix. + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). + allow_fp16_qk_reduction : bool + Whether to use f16 for qk reduction (faster at the cost of slight precision + loss). + rope_scale : Optional[float] + The scale used in RoPE interpolation, if not provided, will be set to + ``1.0``. + rope_theta : Optional[float] + The theta used in RoPE, if not provided, will be set to ``1e4``. + + Returns + ------- + torch.Tensor + The attention output, shape: ``[qo_indptr[-1], num_qo_heads, head_dim]``. + """ check_rotary_mode(rotary_mode) if rope_scale is None: rope_scale = 1.0 @@ -267,6 +423,40 @@ def forward_return_lse( rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): + r"""Compute batch prefill/append attention paged kv-cache. + + Parameters + ---------- + q : torch.Tensor + The query tensor, shape: ``[qo_indptr[-1], num_qo_heads, head_dim]`` + paged_kv_data : torch.Tensor + A 5-D tensor of the reserved paged kv-cache data, shape: + ``[max_num_pages, 2, page_size, num_kv_heads, head_dim]`` + if :attr:`kv_layout` is ``NHD``, or + ``[max_num_pages, 2, num_kv_heads, page_size, head_dim]`` if + :attr:`kv_layout` is ``HND``. + causal : bool + Whether to apply causal mask to the attention matrix. + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). + allow_fp16_qk_reduction : bool + Whether to use f16 for qk reduction (faster at the cost of slight precision + loss). + rope_scale : Optional[float] + The scale used in RoPE interpolation, if not provided, will be set to + ``1.0``. + rope_theta : Optional[float] + The theta used in RoPE, if not provided, will be set to ``1e4``. + + Returns + ------- + V : torch.Tensor + The attention output, shape: ``[qo_indptr[-1], num_qo_heads, head_dim]``. + S : torch.Tensor + The logsumexp of attention output, shape: + ``[qo_indptr[-1], num_qo_heads, head_dim]``. + """ check_rotary_mode(rotary_mode) if rope_scale is None: rope_scale = 1.0 @@ -290,9 +480,31 @@ def forward_return_lse( class BatchPrefillWithRaggedKVCacheWrapper: - r"""Wrapper class of batch_prefill_with_ragged_kv_cache kernel.""" + r"""Wrapper class for prefill/append attention with ragged (tensor) kv-cache for + batch of requests. + + Check :ref:`our tutorial` for ragged kv-cache layout. + + Note + ---- + To accelerate computation, FlashInfer's batch prefill/append attention operators + creates some auxiliary data structures, these data structures can be reused across + multiple prefill/append attention calls (e.g. different Transformer layers). This + wrapper class manages the lifecycle of these data structures. + """ def __init__(self, workspace_buffer: torch.Tensor, kv_layout: str = "NHD"): + r"""Constructor of :class:`BatchDecodeWithRaggedKVCacheWrapper`. + + Parameters + ---------- + workspace_buffer : torch.Tensor + The user reserved workspace buffer used to store auxiliary data structures, + recommended size is 16MB, the device of the workspace buffer should be the + same as the device of the input tensors. + kv_layout : str + The layout of the input k/v tensors, could be either ``NHD`` or ``HND``. + """ check_kv_layout(kv_layout) self._kv_layout = kv_layout self._workspace_buffer = workspace_buffer @@ -303,6 +515,14 @@ def __init__(self, workspace_buffer: torch.Tensor, kv_layout: str = "NHD"): self._kv_indptr = None def reset_workspace_buffer(self, new_workspace_buffer: torch.Tensor): + r"""Reset the workspace buffer. + + Parameters + ---------- + new_workspace_buffer : torch.Tensor + The new workspace buffer, the device of the new workspace buffer should + be the same as the device of the input tensors. + """ self._workspace_buffer = new_workspace_buffer def begin_forward( @@ -312,6 +532,30 @@ def begin_forward( num_qo_heads: int, num_kv_heads: int, ): + r"""Create auxiliary data structures for batch prefill/append attention for + multiple forward calls within the same prefill/append step. + + Parameters + ---------- + qo_indptr : torch.Tensor + The indptr of the query/output tensor, shape: ``[batch_size + 1]``. + kv_indptr : torch.Tensor + The indptr of the key/value tensor, shape: ``[batch_size + 1]``. + num_qo_heads : int + The number of query/output heads. + num_kv_heads : int + The number of key/value heads. + + Notes + ----- + The :meth:`begin_forward` method should be called before any :meth:`forward` or + :meth:`forward_return_lse` calls, auxiliary data structures will be created + during this call and cached for multiple forward calls. + + The ``num_qo_heads`` must be a multiple of ``num_kv_heads``. If ``num_qo_heads`` + is not equal to ``num_kv_heads``, the function will use + `grouped query attention `_. + """ batch_size = len(qo_indptr) - 1 self._qo_indptr = qo_indptr self._kv_indptr = kv_indptr @@ -320,6 +564,7 @@ def begin_forward( ) def end_forward(self): + r"""Clear the auxiliary data structures created by :meth:`begin_forward`.""" self._qo_indptr = None self._kv_indptr = None self._wrapper.end_forward() @@ -335,6 +580,36 @@ def forward( rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): + r"""Compute batch prefill/append attention between query and kv-cache stored in + ragged tensor. + + Parameters + ---------- + q : torch.Tensor + The query tensor, shape: ``[qo_indptr[-1], num_qo_heads, head_dim]`` + k : torch.Tensor + The key tensor, shape: ``[kv_indptr[-1], num_kv_heads, head_dim]`` + v : torch.Tensor + The value tensor, shape: ``[kv_indptr[-1], num_kv_heads, head_dim]`` + causal : bool + Whether to apply causal mask to the attention matrix. + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). + allow_fp16_qk_reduction : bool + Whether to use f16 for qk reduction (faster at the cost of slight precision + loss). + rope_scale : Optional[float] + The scale used in RoPE interpolation, if not provided, will be set to + ``1.0``. + rope_theta : Optional[float] + The theta used in RoPE, if not provided, will be set to ``1e4``. + + Returns + ------- + torch.Tensor + The attention output, shape: ``[qo_indptr[-1], num_qo_heads, head_dim]``. + """ check_rotary_mode(rotary_mode) if rope_scale is None: rope_scale = 1.0 @@ -365,6 +640,38 @@ def forward_return_lse( rope_scale: Optional[float] = None, rope_theta: Optional[float] = None, ): + r"""Compute batch prefill/append attention between query and kv-cache stored in + ragged tensor. Return attention output and logsumexp of attention scores. + + Parameters + ---------- + q : torch.Tensor + The query tensor, shape: ``[qo_indptr[-1], num_qo_heads, head_dim]`` + k : torch.Tensor + The key tensor, shape: ``[kv_indptr[-1], num_kv_heads, head_dim]`` + v : torch.Tensor + The value tensor, shape: ``[kv_indptr[-1], num_kv_heads, head_dim]`` + causal : bool + Whether to apply causal mask to the attention matrix. + rotary_mode : str + Whether to apply RoPE on-the-fly inside attention kernels, could be + ``NONE`` or ``LLAMA`` (LLAMA style rotary embedding). + allow_fp16_qk_reduction : bool + Whether to use f16 for qk reduction (faster at the cost of slight precision + loss). + rope_scale : Optional[float] + The scale used in RoPE interpolation, if not provided, will be set to ``1.0``. + rope_theta : Optional[float] + The theta used in RoPE, if not provided, will be set to ``1e4``. + + Returns + ------- + V : torch.Tensor + The attention output, shape: ``[qo_indptr[-1], num_qo_heads, head_dim]``. + S : torch.Tensor + The logsumexp of attention output, shape: + ``[qo_indptr[-1], num_qo_heads, head_dim]``. + """ check_rotary_mode(rotary_mode) if rope_scale is None: rope_scale = 1.0