import{S as Ds,i as Gs,s as Js,e as o,k as f,w as j,t as p,M as Us,c as n,d as s,m as h,a as r,x as $,h as m,b as l,G as a,g as i,y as b,L as Ks,q as k,o as T,B as x,v as Qs}from"../../../chunks/vendor-hf-doc-builder.js";import{I as ht}from"../../../chunks/IconCopyLink-hf-doc-builder.js";import{C as Bt}from"../../../chunks/CodeBlock-hf-doc-builder.js";function Vs(vs){let u,ct,g,E,st,N,It,at,Wt,dt,A,Ht,et,Ft,Lt,ut,v,z,ot,O,Dt,nt,Gt,gt,D,Jt,vt,_,M,rt,R,Ut,it,Kt,_t,d,Qt,G,Vt,Xt,J,Yt,Zt,wt,U,ts,yt,B,jt,K,ss,$t,I,bt,w,P,lt,W,as,pt,es,kt,c,os,Q,ns,rs,V,is,ls,X,ps,ms,Tt,Y,fs,xt,H,Et,y,q,mt,F,hs,ft,cs,At,C,ds,Z,us,gs,zt,L,Mt;return N=new ht({}),O=new ht({}),R=new ht({}),B=new Bt({props:{code:`from optimum.fx.optimization import Transformation

class ChangeMulToAdd(Transformation):
    def transform(self, graph_module):
        for node in graph_module.graph.nodes:
            if node.op == "call_function" and node.target == operator.mul:
                node.target = operator.add
        return graph_module`,highlighted:`<span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> optimum.fx.optimization <span class="hljs-keyword">import</span> Transformation

<span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">class</span> <span class="hljs-title class_">ChangeMulToAdd</span>(<span class="hljs-title class_ inherited__">Transformation</span>):
<span class="hljs-meta">&gt;&gt;&gt; </span>    <span class="hljs-keyword">def</span> <span class="hljs-title function_">transform</span>(<span class="hljs-params">self, graph_module</span>):
<span class="hljs-meta">&gt;&gt;&gt; </span>        <span class="hljs-keyword">for</span> node <span class="hljs-keyword">in</span> graph_module.graph.nodes:
<span class="hljs-meta">&gt;&gt;&gt; </span>            <span class="hljs-keyword">if</span> node.op == <span class="hljs-string">&quot;call_function&quot;</span> <span class="hljs-keyword">and</span> node.target == operator.mul:
<span class="hljs-meta">&gt;&gt;&gt; </span>                node.target = operator.add
<span class="hljs-meta">&gt;&gt;&gt; </span>        <span class="hljs-keyword">return</span> graph_module`}}),I=new Bt({props:{code:`from transformers import BertModel
from transformers.utils.fx import symbolic_trace

model = BertModel.from_pretrained("bert-base-uncased")
traced = symbolic_trace(
    model,
    input_names=["input_ids", "attention_mask", "token_type_ids"],
)

transformation = ChangeMulToAdd()
transformed_model = transformation(traced)`,highlighted:`<span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> BertModel
<span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> transformers.utils.fx <span class="hljs-keyword">import</span> symbolic_trace

<span class="hljs-meta">&gt;&gt;&gt; </span>model = BertModel.from_pretrained(<span class="hljs-string">&quot;bert-base-uncased&quot;</span>)
<span class="hljs-meta">&gt;&gt;&gt; </span>traced = symbolic_trace(
<span class="hljs-meta">&gt;&gt;&gt; </span>    model,
<span class="hljs-meta">&gt;&gt;&gt; </span>    input_names=[<span class="hljs-string">&quot;input_ids&quot;</span>, <span class="hljs-string">&quot;attention_mask&quot;</span>, <span class="hljs-string">&quot;token_type_ids&quot;</span>],
<span class="hljs-meta">&gt;&gt;&gt; </span>)

<span class="hljs-meta">&gt;&gt;&gt; </span>transformation = ChangeMulToAdd()
<span class="hljs-meta">&gt;&gt;&gt; </span>transformed_model = transformation(traced)`}}),W=new ht({}),H=new Bt({props:{code:`from optimum.fx.optimization import ReversibleTransformation

class MulToMulTimesTwo(ReversibleTransformation):
    def transform(self, graph_module):
        for node in graph_module.graph.nodes:
            if node.op == "call_function" and node.target == operator.mul:
                x, y = node.args
                node.args = (2 * x, y)
        return graph_module

    def reverse(self, graph_module):
        for node in graph_module.graph.nodes:
            if node.op == "call_function" and node.target == operator.mul:
                x, y = node.args
                node.args = (x / 2, y)
        return graph_module`,highlighted:`<span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> optimum.fx.optimization <span class="hljs-keyword">import</span> ReversibleTransformation

<span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">class</span> <span class="hljs-title class_">MulToMulTimesTwo</span>(<span class="hljs-title class_ inherited__">ReversibleTransformation</span>):
<span class="hljs-meta">&gt;&gt;&gt; </span>    <span class="hljs-keyword">def</span> <span class="hljs-title function_">transform</span>(<span class="hljs-params">self, graph_module</span>):
<span class="hljs-meta">&gt;&gt;&gt; </span>        <span class="hljs-keyword">for</span> node <span class="hljs-keyword">in</span> graph_module.graph.nodes:
<span class="hljs-meta">&gt;&gt;&gt; </span>            <span class="hljs-keyword">if</span> node.op == <span class="hljs-string">&quot;call_function&quot;</span> <span class="hljs-keyword">and</span> node.target == operator.mul:
<span class="hljs-meta">&gt;&gt;&gt; </span>                x, y = node.args
<span class="hljs-meta">&gt;&gt;&gt; </span>                node.args = (<span class="hljs-number">2</span> * x, y)
<span class="hljs-meta">&gt;&gt;&gt; </span>        <span class="hljs-keyword">return</span> graph_module

<span class="hljs-meta">&gt;&gt;&gt; </span>    <span class="hljs-keyword">def</span> <span class="hljs-title function_">reverse</span>(<span class="hljs-params">self, graph_module</span>):
<span class="hljs-meta">&gt;&gt;&gt; </span>        <span class="hljs-keyword">for</span> node <span class="hljs-keyword">in</span> graph_module.graph.nodes:
<span class="hljs-meta">&gt;&gt;&gt; </span>            <span class="hljs-keyword">if</span> node.op == <span class="hljs-string">&quot;call_function&quot;</span> <span class="hljs-keyword">and</span> node.target == operator.mul:
<span class="hljs-meta">&gt;&gt;&gt; </span>                x, y = node.args
<span class="hljs-meta">&gt;&gt;&gt; </span>                node.args = (x / <span class="hljs-number">2</span>, y)
<span class="hljs-meta">&gt;&gt;&gt; </span>        <span class="hljs-keyword">return</span> graph_module`}}),F=new ht({}),L=new Bt({props:{code:`from optimum.fx.optimization import compose
composition = compose(MulToMulTimesTwo(), ChangeMulToAdd())`,highlighted:`<span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> optimum.fx.optimization <span class="hljs-keyword">import</span> compose
<span class="hljs-meta">&gt;&gt;&gt; </span>composition = compose(MulToMulTimesTwo(), ChangeMulToAdd())`}}),{c(){u=o("meta"),ct=f(),g=o("h1"),E=o("a"),st=o("span"),j(N.$$.fragment),It=f(),at=o("span"),Wt=p("Optimization"),dt=f(),A=o("p"),Ht=p("The "),et=o("code"),Ft=p("optimum.fx.optimization"),Lt=p(" module provides a set of torch.fx graph transformations, along with classes and functions to write your own transformations and compose them."),ut=f(),v=o("h2"),z=o("a"),ot=o("span"),j(O.$$.fragment),Dt=f(),nt=o("span"),Gt=p("The transformation guide"),gt=f(),D=o("p"),Jt=p("In \u{1F917} Optimum, there are two kinds of transformations: reversible and non-reversible transformations."),vt=f(),_=o("h3"),M=o("a"),rt=o("span"),j(R.$$.fragment),Ut=f(),it=o("span"),Kt=p("Write a non-reversible transformation"),_t=f(),d=o("p"),Qt=p("The most basic case of transformations is non-reversible transformations. Those transformations cannot be reversed, meaning that after applying them to a graph module, there is no way to get the original model back. To implement such transformations in \u{1F917} Optimum, it is very easy: you just need to subclass "),G=o("a"),Vt=p("Transformation"),Xt=p(" and implement the "),J=o("a"),Yt=p("transform()"),Zt=p(" method."),wt=f(),U=o("p"),ts=p("For instance, the following transformation changes all the multiplications to additions:"),yt=f(),j(B.$$.fragment),jt=f(),K=o("p"),ss=p("After implementing it, your transformation can be used as a regular function:"),$t=f(),j(I.$$.fragment),bt=f(),w=o("h3"),P=o("a"),lt=o("span"),j(W.$$.fragment),as=f(),pt=o("span"),es=p("Write a reversible transformation"),kt=f(),c=o("p"),os=p("A reversible transformation implements both the transformation and its reverse, allowing to retrieve the original model from the transformed one. To implement such transformation, you need to subclass "),Q=o("a"),ns=p("ReversibleTransformation"),rs=p(" and implement the "),V=o("a"),is=p("transform()"),ls=p(" and "),X=o("a"),ps=p("reverse()"),ms=p(" methods."),Tt=f(),Y=o("p"),fs=p("For instance, the following transformation is reversible:"),xt=f(),j(H.$$.fragment),Et=f(),y=o("h3"),q=o("a"),mt=o("span"),j(F.$$.fragment),hs=f(),ft=o("span"),cs=p("Composing transformations together"),At=f(),C=o("p"),ds=p("As applying multiple transformations in chain is needed more often that not, "),Z=o("a"),us=p("compose()"),gs=p(" is provided. It is an utility function that allows you to create a transformation by chaining multiple other transformations."),zt=f(),j(L.$$.fragment),this.h()},l(t){const e=Us('[data-svelte="svelte-1phssyn"]',document.head);u=n(e,"META",{name:!0,content:!0}),e.forEach(s),ct=h(t),g=n(t,"H1",{class:!0});var Pt=r(g);E=n(Pt,"A",{id:!0,class:!0,href:!0});var _s=r(E);st=n(_s,"SPAN",{});var ws=r(st);$(N.$$.fragment,ws),ws.forEach(s),_s.forEach(s),It=h(Pt),at=n(Pt,"SPAN",{});var ys=r(at);Wt=m(ys,"Optimization"),ys.forEach(s),Pt.forEach(s),dt=h(t),A=n(t,"P",{});var qt=r(A);Ht=m(qt,"The "),et=n(qt,"CODE",{});var js=r(et);Ft=m(js,"optimum.fx.optimization"),js.forEach(s),Lt=m(qt," module provides a set of torch.fx graph transformations, along with classes and functions to write your own transformations and compose them."),qt.forEach(s),ut=h(t),v=n(t,"H2",{class:!0});var Ct=r(v);z=n(Ct,"A",{id:!0,class:!0,href:!0});var $s=r(z);ot=n($s,"SPAN",{});var bs=r(ot);$(O.$$.fragment,bs),bs.forEach(s),$s.forEach(s),Dt=h(Ct),nt=n(Ct,"SPAN",{});var ks=r(nt);Gt=m(ks,"The transformation guide"),ks.forEach(s),Ct.forEach(s),gt=h(t),D=n(t,"P",{});var Ts=r(D);Jt=m(Ts,"In \u{1F917} Optimum, there are two kinds of transformations: reversible and non-reversible transformations."),Ts.forEach(s),vt=h(t),_=n(t,"H3",{class:!0});var St=r(_);M=n(St,"A",{id:!0,class:!0,href:!0});var xs=r(M);rt=n(xs,"SPAN",{});var Es=r(rt);$(R.$$.fragment,Es),Es.forEach(s),xs.forEach(s),Ut=h(St),it=n(St,"SPAN",{});var As=r(it);Kt=m(As,"Write a non-reversible transformation"),As.forEach(s),St.forEach(s),_t=h(t),d=n(t,"P",{});var tt=r(d);Qt=m(tt,"The most basic case of transformations is non-reversible transformations. Those transformations cannot be reversed, meaning that after applying them to a graph module, there is no way to get the original model back. To implement such transformations in \u{1F917} Optimum, it is very easy: you just need to subclass "),G=n(tt,"A",{href:!0});var zs=r(G);Vt=m(zs,"Transformation"),zs.forEach(s),Xt=m(tt," and implement the "),J=n(tt,"A",{href:!0});var Ms=r(J);Yt=m(Ms,"transform()"),Ms.forEach(s),Zt=m(tt," method."),tt.forEach(s),wt=h(t),U=n(t,"P",{});var Ps=r(U);ts=m(Ps,"For instance, the following transformation changes all the multiplications to additions:"),Ps.forEach(s),yt=h(t),$(B.$$.fragment,t),jt=h(t),K=n(t,"P",{});var qs=r(K);ss=m(qs,"After implementing it, your transformation can be used as a regular function:"),qs.forEach(s),$t=h(t),$(I.$$.fragment,t),bt=h(t),w=n(t,"H3",{class:!0});var Nt=r(w);P=n(Nt,"A",{id:!0,class:!0,href:!0});var Cs=r(P);lt=n(Cs,"SPAN",{});var Ss=r(lt);$(W.$$.fragment,Ss),Ss.forEach(s),Cs.forEach(s),as=h(Nt),pt=n(Nt,"SPAN",{});var Ns=r(pt);es=m(Ns,"Write a reversible transformation"),Ns.forEach(s),Nt.forEach(s),kt=h(t),c=n(t,"P",{});var S=r(c);os=m(S,"A reversible transformation implements both the transformation and its reverse, allowing to retrieve the original model from the transformed one. To implement such transformation, you need to subclass "),Q=n(S,"A",{href:!0});var Os=r(Q);ns=m(Os,"ReversibleTransformation"),Os.forEach(s),rs=m(S," and implement the "),V=n(S,"A",{href:!0});var Rs=r(V);is=m(Rs,"transform()"),Rs.forEach(s),ls=m(S," and "),X=n(S,"A",{href:!0});var Bs=r(X);ps=m(Bs,"reverse()"),Bs.forEach(s),ms=m(S," methods."),S.forEach(s),Tt=h(t),Y=n(t,"P",{});var Is=r(Y);fs=m(Is,"For instance, the following transformation is reversible:"),Is.forEach(s),xt=h(t),$(H.$$.fragment,t),Et=h(t),y=n(t,"H3",{class:!0});var Ot=r(y);q=n(Ot,"A",{id:!0,class:!0,href:!0});var Ws=r(q);mt=n(Ws,"SPAN",{});var Hs=r(mt);$(F.$$.fragment,Hs),Hs.forEach(s),Ws.forEach(s),hs=h(Ot),ft=n(Ot,"SPAN",{});var Fs=r(ft);cs=m(Fs,"Composing transformations together"),Fs.forEach(s),Ot.forEach(s),At=h(t),C=n(t,"P",{});var Rt=r(C);ds=m(Rt,"As applying multiple transformations in chain is needed more often that not, "),Z=n(Rt,"A",{href:!0});var Ls=r(Z);us=m(Ls,"compose()"),Ls.forEach(s),gs=m(Rt," is provided. It is an utility function that allows you to create a transformation by chaining multiple other transformations."),Rt.forEach(s),zt=h(t),$(L.$$.fragment,t),this.h()},h(){l(u,"name","hf:doc:metadata"),l(u,"content",JSON.stringify(Xs)),l(E,"id","optimization"),l(E,"class","header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full"),l(E,"href","#optimization"),l(g,"class","relative group"),l(z,"id","the-transformation-guide"),l(z,"class","header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full"),l(z,"href","#the-transformation-guide"),l(v,"class","relative group"),l(M,"id","write-a-nonreversible-transformation"),l(M,"class","header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full"),l(M,"href","#write-a-nonreversible-transformation"),l(_,"class","relative group"),l(G,"href","/docs/optimum/pr_444/en/torch_fx/package_reference/optimization#optimum.fx.optimization.Transformation"),l(J,"href","/docs/optimum/pr_444/en/torch_fx/package_reference/optimization#optimum.fx.optimization.Transformation.transform"),l(P,"id","write-a-reversible-transformation"),l(P,"class","header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full"),l(P,"href","#write-a-reversible-transformation"),l(w,"class","relative group"),l(Q,"href","/docs/optimum/pr_444/en/torch_fx/package_reference/optimization#optimum.fx.optimization.ReversibleTransformation"),l(V,"href","/docs/optimum/pr_444/en/torch_fx/package_reference/optimization#optimum.fx.optimization.Transformation.transform"),l(X,"href","/docs/optimum/pr_444/en/torch_fx/package_reference/optimization#optimum.fx.optimization.ReversibleTransformation.reverse"),l(q,"id","composing-transformations-together"),l(q,"class","header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full"),l(q,"href","#composing-transformations-together"),l(y,"class","relative group"),l(Z,"href","/docs/optimum/pr_444/en/torch_fx/package_reference/optimization#optimum.fx.optimization.compose")},m(t,e){a(document.head,u),i(t,ct,e),i(t,g,e),a(g,E),a(E,st),b(N,st,null),a(g,It),a(g,at),a(at,Wt),i(t,dt,e),i(t,A,e),a(A,Ht),a(A,et),a(et,Ft),a(A,Lt),i(t,ut,e),i(t,v,e),a(v,z),a(z,ot),b(O,ot,null),a(v,Dt),a(v,nt),a(nt,Gt),i(t,gt,e),i(t,D,e),a(D,Jt),i(t,vt,e),i(t,_,e),a(_,M),a(M,rt),b(R,rt,null),a(_,Ut),a(_,it),a(it,Kt),i(t,_t,e),i(t,d,e),a(d,Qt),a(d,G),a(G,Vt),a(d,Xt),a(d,J),a(J,Yt),a(d,Zt),i(t,wt,e),i(t,U,e),a(U,ts),i(t,yt,e),b(B,t,e),i(t,jt,e),i(t,K,e),a(K,ss),i(t,$t,e),b(I,t,e),i(t,bt,e),i(t,w,e),a(w,P),a(P,lt),b(W,lt,null),a(w,as),a(w,pt),a(pt,es),i(t,kt,e),i(t,c,e),a(c,os),a(c,Q),a(Q,ns),a(c,rs),a(c,V),a(V,is),a(c,ls),a(c,X),a(X,ps),a(c,ms),i(t,Tt,e),i(t,Y,e),a(Y,fs),i(t,xt,e),b(H,t,e),i(t,Et,e),i(t,y,e),a(y,q),a(q,mt),b(F,mt,null),a(y,hs),a(y,ft),a(ft,cs),i(t,At,e),i(t,C,e),a(C,ds),a(C,Z),a(Z,us),a(C,gs),i(t,zt,e),b(L,t,e),Mt=!0},p:Ks,i(t){Mt||(k(N.$$.fragment,t),k(O.$$.fragment,t),k(R.$$.fragment,t),k(B.$$.fragment,t),k(I.$$.fragment,t),k(W.$$.fragment,t),k(H.$$.fragment,t),k(F.$$.fragment,t),k(L.$$.fragment,t),Mt=!0)},o(t){T(N.$$.fragment,t),T(O.$$.fragment,t),T(R.$$.fragment,t),T(B.$$.fragment,t),T(I.$$.fragment,t),T(W.$$.fragment,t),T(H.$$.fragment,t),T(F.$$.fragment,t),T(L.$$.fragment,t),Mt=!1},d(t){s(u),t&&s(ct),t&&s(g),x(N),t&&s(dt),t&&s(A),t&&s(ut),t&&s(v),x(O),t&&s(gt),t&&s(D),t&&s(vt),t&&s(_),x(R),t&&s(_t),t&&s(d),t&&s(wt),t&&s(U),t&&s(yt),x(B,t),t&&s(jt),t&&s(K),t&&s($t),x(I,t),t&&s(bt),t&&s(w),x(W),t&&s(kt),t&&s(c),t&&s(Tt),t&&s(Y),t&&s(xt),x(H,t),t&&s(Et),t&&s(y),x(F),t&&s(At),t&&s(C),t&&s(zt),x(L,t)}}}const Xs={local:"optimization",sections:[{local:"the-transformation-guide",sections:[{local:"write-a-nonreversible-transformation",title:"Write a non-reversible transformation"},{local:"write-a-reversible-transformation",title:"Write a reversible transformation"},{local:"composing-transformations-together",title:"Composing transformations together"}],title:"The transformation guide"}],title:"Optimization"};function Ys(vs){return Qs(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class aa extends Ds{constructor(u){super();Gs(this,u,Ys,Vs,Js,{})}}export{aa as default,Xs as metadata};
