Buckets:
| import{s as _e,n as Ne,o as xe}from"../chunks/scheduler.d586627e.js";import{S as Ve,i as Re,g as M,s,r as n,A as Qe,h as d,f as a,c as o,j as ke,u as r,x as w,k as Ye,y as Ee,a as l,v as i,d as c,t as m,w as p}from"../chunks/index.8589a59c.js";import{C as y}from"../chunks/CodeBlock.47c46d2c.js";import{H as F,E as Fe}from"../chunks/EditOnGithub.073dfa26.js";function Se(he){let u,z,S,P,J,K,j,$e=`O paralelismo surgiu como uma estratégia para treinar modelos grandes em hardware limitado e aumentar a velocidade | |
| de treinamento em várias órdens de magnitude. Na Hugging Face criamos a biblioteca <a href="https://huggingface.co/docs/accelerate" rel="nofollow">🤗 Accelerate</a> | |
| para ajudar os usuários a treinar modelos 🤗 Transformers com qualquer configuração distribuída, seja em uma máquina | |
| com múltiplos GPUs ou em múltiplos GPUs distribuidos entre muitas máquinas. Neste tutorial, você irá aprender como | |
| personalizar seu laço de treinamento de PyTorch para poder treinar em ambientes distribuídos.`,L,T,q,f,ge="De início, instale o 🤗 Accelerate:",D,b,O,U,Ie=`Logo, devemos importar e criar um objeto <a href="https://huggingface.co/docs/accelerate/package_reference/accelerator#accelerate.Accelerator" rel="nofollow"><code>Accelerator</code></a>. | |
| O <code>Accelerator</code> detectará automáticamente a configuração distribuída disponível e inicializará todos os | |
| componentes necessários para o treinamento. Não há necessidade portanto de especificar o dispositivo onde deve colocar seu modelo.`,ee,h,te,$,ae,g,Ce=`Passe todos os objetos relevantes ao treinamento para o método <a href="https://huggingface.co/docs/accelerate/package_reference/accelerator#accelerate.Accelerator.prepare" rel="nofollow"><code>prepare</code></a>. | |
| Isto inclui os DataLoaders de treino e evaluação, um modelo e um otimizador:`,le,I,se,C,oe,B,Be='Por último, substitua o <code>loss.backward()</code> padrão em seu laço de treinamento com o método <a href="https://huggingface.co/docs/accelerate/package_reference/accelerator#accelerate.Accelerator.backward" rel="nofollow"><code>backward</code></a> do 🤗 Accelerate:',ne,Z,re,A,Ze=`Como se poder ver no seguinte código, só precisará adicionar quatro linhas de código ao seu laço de treinamento | |
| para habilitar o treinamento distribuído!`,ie,v,ce,G,me,W,Ae="Quando tiver adicionado as linhas de código relevantes, inicie o treinamento por um script ou notebook como o Colab.",pe,X,Me,k,ve="Se estiver rodando seu treinamento em um Script, execute o seguinte comando para criar e guardar um arquivo de configuração:",de,Y,we,_,Ge="Comece o treinamento com:",ue,N,ye,x,Je,V,We=`O 🤗 Accelerate pode rodar em um notebook, por exemplo, se estiver planejando usar as TPUs do Google Colab. | |
| Encapsule o código responsável pelo treinamento de uma função e passe-o ao <code>notebook_launcher</code>:`,je,R,Te,Q,Xe='Para obter mais informações sobre o 🤗 Accelerate e suas numerosas funções, consulte a <a href="https://huggingface.co/docs/accelerate/index" rel="nofollow">documentación</a>.',fe,E,be,H,Ue;return J=new F({props:{title:"Treinamento distribuído com o 🤗 Accelerate",local:"treinamento-distribuído-com-o--accelerate",headingTag:"h1"}}),T=new F({props:{title:"Configuração",local:"configuração",headingTag:"h2"}}),b=new y({props:{code:"cGlwJTIwaW5zdGFsbCUyMGFjY2VsZXJhdGU=",highlighted:"pip install accelerate",wrap:!1}}),h=new y({props:{code:"ZnJvbSUyMGFjY2VsZXJhdGUlMjBpbXBvcnQlMjBBY2NlbGVyYXRvciUwQSUwQWFjY2VsZXJhdG9yJTIwJTNEJTIwQWNjZWxlcmF0b3IoKQ==",highlighted:`<span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> accelerate <span class="hljs-keyword">import</span> Accelerator | |
| <span class="hljs-meta">>>> </span>accelerator = Accelerator()`,wrap:!1}}),$=new F({props:{title:"Preparando a aceleração",local:"preparando-a-aceleração",headingTag:"h2"}}),I=new y({props:{code:"dHJhaW5fZGF0YWxvYWRlciUyQyUyMGV2YWxfZGF0YWxvYWRlciUyQyUyMG1vZGVsJTJDJTIwb3B0aW1pemVyJTIwJTNEJTIwYWNjZWxlcmF0b3IucHJlcGFyZSglMEElMjAlMjAlMjAlMjB0cmFpbl9kYXRhbG9hZGVyJTJDJTIwZXZhbF9kYXRhbG9hZGVyJTJDJTIwbW9kZWwlMkMlMjBvcHRpbWl6ZXIlMEEp",highlighted:`<span class="hljs-meta">>>> </span>train_dataloader, eval_dataloader, model, optimizer = accelerator.prepare( | |
| <span class="hljs-meta">... </span> train_dataloader, eval_dataloader, model, optimizer | |
| <span class="hljs-meta">... </span>)`,wrap:!1}}),C=new F({props:{title:"Backward",local:"backward",headingTag:"h2"}}),Z=new y({props:{code:"Zm9yJTIwZXBvY2glMjBpbiUyMHJhbmdlKG51bV9lcG9jaHMpJTNBJTBBJTIwJTIwJTIwJTIwZm9yJTIwYmF0Y2glMjBpbiUyMHRyYWluX2RhdGFsb2FkZXIlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBvdXRwdXRzJTIwJTNEJTIwbW9kZWwoKipiYXRjaCklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBsb3NzJTIwJTNEJTIwb3V0cHV0cy5sb3NzJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwYWNjZWxlcmF0b3IuYmFja3dhcmQobG9zcyklMEElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBvcHRpbWl6ZXIuc3RlcCgpJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwbHJfc2NoZWR1bGVyLnN0ZXAoKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMG9wdGltaXplci56ZXJvX2dyYWQoKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHByb2dyZXNzX2Jhci51cGRhdGUoMSk=",highlighted:`<span class="hljs-meta">>>> </span><span class="hljs-keyword">for</span> epoch <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(num_epochs): | |
| <span class="hljs-meta">... </span> <span class="hljs-keyword">for</span> batch <span class="hljs-keyword">in</span> train_dataloader: | |
| <span class="hljs-meta">... </span> outputs = model(**batch) | |
| <span class="hljs-meta">... </span> loss = outputs.loss | |
| <span class="hljs-meta">... </span> accelerator.backward(loss) | |
| <span class="hljs-meta">... </span> optimizer.step() | |
| <span class="hljs-meta">... </span> lr_scheduler.step() | |
| <span class="hljs-meta">... </span> optimizer.zero_grad() | |
| <span class="hljs-meta">... </span> progress_bar.update(<span class="hljs-number">1</span>)`,wrap:!1}}),v=new y({props:{code:"JTJCJTIwZnJvbSUyMGFjY2VsZXJhdGUlMjBpbXBvcnQlMjBBY2NlbGVyYXRvciUwQSUyMCUyMGZyb20lMjB0cmFuc2Zvcm1lcnMlMjBpbXBvcnQlMjBBZGFtVyUyQyUyMEF1dG9Nb2RlbEZvclNlcXVlbmNlQ2xhc3NpZmljYXRpb24lMkMlMjBnZXRfc2NoZWR1bGVyJTBBJTBBJTJCJTIwYWNjZWxlcmF0b3IlMjAlM0QlMjBBY2NlbGVyYXRvcigpJTBBJTBBJTIwJTIwbW9kZWwlMjAlM0QlMjBBdXRvTW9kZWxGb3JTZXF1ZW5jZUNsYXNzaWZpY2F0aW9uLmZyb21fcHJldHJhaW5lZChjaGVja3BvaW50JTJDJTIwbnVtX2xhYmVscyUzRDIpJTBBJTIwJTIwb3B0aW1pemVyJTIwJTNEJTIwQWRhbVcobW9kZWwucGFyYW1ldGVycygpJTJDJTIwbHIlM0QzZS01KSUwQSUwQS0lMjBkZXZpY2UlMjAlM0QlMjB0b3JjaC5kZXZpY2UoJTIyY3VkYSUyMiklMjBpZiUyMHRvcmNoLmN1ZGEuaXNfYXZhaWxhYmxlKCklMjBlbHNlJTIwdG9yY2guZGV2aWNlKCUyMmNwdSUyMiklMEEtJTIwbW9kZWwudG8oZGV2aWNlKSUwQSUwQSUyQiUyMHRyYWluX2RhdGFsb2FkZXIlMkMlMjBldmFsX2RhdGFsb2FkZXIlMkMlMjBtb2RlbCUyQyUyMG9wdGltaXplciUyMCUzRCUyMGFjY2VsZXJhdG9yLnByZXBhcmUoJTBBJTJCJTIwJTIwJTIwJTIwJTIwdHJhaW5fZGF0YWxvYWRlciUyQyUyMGV2YWxfZGF0YWxvYWRlciUyQyUyMG1vZGVsJTJDJTIwb3B0aW1pemVyJTBBJTJCJTIwKSUwQSUwQSUyMCUyMG51bV9lcG9jaHMlMjAlM0QlMjAzJTBBJTIwJTIwbnVtX3RyYWluaW5nX3N0ZXBzJTIwJTNEJTIwbnVtX2Vwb2NocyUyMColMjBsZW4odHJhaW5fZGF0YWxvYWRlciklMEElMjAlMjBscl9zY2hlZHVsZXIlMjAlM0QlMjBnZXRfc2NoZWR1bGVyKCUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMmxpbmVhciUyMiUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMG9wdGltaXplciUzRG9wdGltaXplciUyQyUwQSUyMCUyMCUyMCUyMCUyMCUyMG51bV93YXJtdXBfc3RlcHMlM0QwJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwbnVtX3RyYWluaW5nX3N0ZXBzJTNEbnVtX3RyYWluaW5nX3N0ZXBzJTBBJTIwJTIwKSUwQSUwQSUyMCUyMHByb2dyZXNzX2JhciUyMCUzRCUyMHRxZG0ocmFuZ2UobnVtX3RyYWluaW5nX3N0ZXBzKSklMEElMEElMjAlMjBtb2RlbC50cmFpbigpJTBBJTIwJTIwZm9yJTIwZXBvY2glMjBpbiUyMHJhbmdlKG51bV9lcG9jaHMpJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwZm9yJTIwYmF0Y2glMjBpbiUyMHRyYWluX2RhdGFsb2FkZXIlM0ElMEEtJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwYmF0Y2glMjAlM0QlMjAlN0JrJTNBJTIwdi50byhkZXZpY2UpJTIwZm9yJTIwayUyQyUyMHYlMjBpbiUyMGJhdGNoLml0ZW1zKCklN0QlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBvdXRwdXRzJTIwJTNEJTIwbW9kZWwoKipiYXRjaCklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBsb3NzJTIwJTNEJTIwb3V0cHV0cy5sb3NzJTBBLSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGxvc3MuYmFja3dhcmQoKSUwQSUyQiUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGFjY2VsZXJhdG9yLmJhY2t3YXJkKGxvc3MpJTBBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwb3B0aW1pemVyLnN0ZXAoKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMGxyX3NjaGVkdWxlci5zdGVwKCklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBvcHRpbWl6ZXIuemVyb19ncmFkKCklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBwcm9ncmVzc19iYXIudXBkYXRlKDEp",highlighted:`<span class="hljs-addition">+ from accelerate import Accelerator</span> | |
| from transformers import AdamW, AutoModelForSequenceClassification, get_scheduler | |
| <span class="hljs-addition">+ accelerator = Accelerator()</span> | |
| model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2) | |
| optimizer = AdamW(model.parameters(), lr=3e-5) | |
| <span class="hljs-deletion">- device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")</span> | |
| <span class="hljs-deletion">- model.to(device)</span> | |
| <span class="hljs-addition">+ train_dataloader, eval_dataloader, model, optimizer = accelerator.prepare(</span> | |
| <span class="hljs-addition">+ train_dataloader, eval_dataloader, model, optimizer</span> | |
| <span class="hljs-addition">+ )</span> | |
| num_epochs = 3 | |
| num_training_steps = num_epochs * len(train_dataloader) | |
| lr_scheduler = get_scheduler( | |
| "linear", | |
| optimizer=optimizer, | |
| num_warmup_steps=0, | |
| num_training_steps=num_training_steps | |
| ) | |
| progress_bar = tqdm(range(num_training_steps)) | |
| model.train() | |
| for epoch in range(num_epochs): | |
| for batch in train_dataloader: | |
| <span class="hljs-deletion">- batch = {k: v.to(device) for k, v in batch.items()}</span> | |
| outputs = model(**batch) | |
| loss = outputs.loss | |
| <span class="hljs-deletion">- loss.backward()</span> | |
| <span class="hljs-addition">+ accelerator.backward(loss)</span> | |
| optimizer.step() | |
| lr_scheduler.step() | |
| optimizer.zero_grad() | |
| progress_bar.update(1)`,wrap:!1}}),G=new F({props:{title:"Treinamento",local:"treinamento",headingTag:"h2"}}),X=new F({props:{title:"Treinamento em um Script",local:"treinamento-em-um-script",headingTag:"h3"}}),Y=new y({props:{code:"YWNjZWxlcmF0ZSUyMGNvbmZpZw==",highlighted:"accelerate config",wrap:!1}}),N=new y({props:{code:"YWNjZWxlcmF0ZSUyMGxhdW5jaCUyMHRyYWluLnB5",highlighted:"accelerate launch train.py",wrap:!1}}),x=new F({props:{title:"Treinamento em um Notebook",local:"treinamento-em-um-notebook",headingTag:"h3"}}),R=new y({props:{code:"ZnJvbSUyMGFjY2VsZXJhdGUlMjBpbXBvcnQlMjBub3RlYm9va19sYXVuY2hlciUwQSUwQW5vdGVib29rX2xhdW5jaGVyKHRyYWluaW5nX2Z1bmN0aW9uKQ==",highlighted:`<span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> accelerate <span class="hljs-keyword">import</span> notebook_launcher | |
| <span class="hljs-meta">>>> </span>notebook_launcher(training_function)`,wrap:!1}}),E=new Fe({props:{source:"https://github.com/huggingface/transformers/blob/main/docs/source/pt/accelerate.md"}}),{c(){u=M("meta"),z=s(),S=M("p"),P=s(),n(J.$$.fragment),K=s(),j=M("p"),j.innerHTML=$e,L=s(),n(T.$$.fragment),q=s(),f=M("p"),f.textContent=ge,D=s(),n(b.$$.fragment),O=s(),U=M("p"),U.innerHTML=Ie,ee=s(),n(h.$$.fragment),te=s(),n($.$$.fragment),ae=s(),g=M("p"),g.innerHTML=Ce,le=s(),n(I.$$.fragment),se=s(),n(C.$$.fragment),oe=s(),B=M("p"),B.innerHTML=Be,ne=s(),n(Z.$$.fragment),re=s(),A=M("p"),A.textContent=Ze,ie=s(),n(v.$$.fragment),ce=s(),n(G.$$.fragment),me=s(),W=M("p"),W.textContent=Ae,pe=s(),n(X.$$.fragment),Me=s(),k=M("p"),k.textContent=ve,de=s(),n(Y.$$.fragment),we=s(),_=M("p"),_.textContent=Ge,ue=s(),n(N.$$.fragment),ye=s(),n(x.$$.fragment),Je=s(),V=M("p"),V.innerHTML=We,je=s(),n(R.$$.fragment),Te=s(),Q=M("p"),Q.innerHTML=Xe,fe=s(),n(E.$$.fragment),be=s(),H=M("p"),this.h()},l(e){const t=Qe("svelte-u9bgzb",document.head);u=d(t,"META",{name:!0,content:!0}),t.forEach(a),z=o(e),S=d(e,"P",{}),ke(S).forEach(a),P=o(e),r(J.$$.fragment,e),K=o(e),j=d(e,"P",{"data-svelte-h":!0}),w(j)!=="svelte-1wiu3fb"&&(j.innerHTML=$e),L=o(e),r(T.$$.fragment,e),q=o(e),f=d(e,"P",{"data-svelte-h":!0}),w(f)!=="svelte-t6m1zf"&&(f.textContent=ge),D=o(e),r(b.$$.fragment,e),O=o(e),U=d(e,"P",{"data-svelte-h":!0}),w(U)!=="svelte-1rphp5p"&&(U.innerHTML=Ie),ee=o(e),r(h.$$.fragment,e),te=o(e),r($.$$.fragment,e),ae=o(e),g=d(e,"P",{"data-svelte-h":!0}),w(g)!=="svelte-iagz26"&&(g.innerHTML=Ce),le=o(e),r(I.$$.fragment,e),se=o(e),r(C.$$.fragment,e),oe=o(e),B=d(e,"P",{"data-svelte-h":!0}),w(B)!=="svelte-1a4hz8x"&&(B.innerHTML=Be),ne=o(e),r(Z.$$.fragment,e),re=o(e),A=d(e,"P",{"data-svelte-h":!0}),w(A)!=="svelte-1eeg6uf"&&(A.textContent=Ze),ie=o(e),r(v.$$.fragment,e),ce=o(e),r(G.$$.fragment,e),me=o(e),W=d(e,"P",{"data-svelte-h":!0}),w(W)!=="svelte-1ugx3dc"&&(W.textContent=Ae),pe=o(e),r(X.$$.fragment,e),Me=o(e),k=d(e,"P",{"data-svelte-h":!0}),w(k)!=="svelte-o59jjd"&&(k.textContent=ve),de=o(e),r(Y.$$.fragment,e),we=o(e),_=d(e,"P",{"data-svelte-h":!0}),w(_)!=="svelte-257ccc"&&(_.textContent=Ge),ue=o(e),r(N.$$.fragment,e),ye=o(e),r(x.$$.fragment,e),Je=o(e),V=d(e,"P",{"data-svelte-h":!0}),w(V)!=="svelte-12l65dl"&&(V.innerHTML=We),je=o(e),r(R.$$.fragment,e),Te=o(e),Q=d(e,"P",{"data-svelte-h":!0}),w(Q)!=="svelte-8c3jdl"&&(Q.innerHTML=Xe),fe=o(e),r(E.$$.fragment,e),be=o(e),H=d(e,"P",{}),ke(H).forEach(a),this.h()},h(){Ye(u,"name","hf:doc:metadata"),Ye(u,"content",He)},m(e,t){Ee(document.head,u),l(e,z,t),l(e,S,t),l(e,P,t),i(J,e,t),l(e,K,t),l(e,j,t),l(e,L,t),i(T,e,t),l(e,q,t),l(e,f,t),l(e,D,t),i(b,e,t),l(e,O,t),l(e,U,t),l(e,ee,t),i(h,e,t),l(e,te,t),i($,e,t),l(e,ae,t),l(e,g,t),l(e,le,t),i(I,e,t),l(e,se,t),i(C,e,t),l(e,oe,t),l(e,B,t),l(e,ne,t),i(Z,e,t),l(e,re,t),l(e,A,t),l(e,ie,t),i(v,e,t),l(e,ce,t),i(G,e,t),l(e,me,t),l(e,W,t),l(e,pe,t),i(X,e,t),l(e,Me,t),l(e,k,t),l(e,de,t),i(Y,e,t),l(e,we,t),l(e,_,t),l(e,ue,t),i(N,e,t),l(e,ye,t),i(x,e,t),l(e,Je,t),l(e,V,t),l(e,je,t),i(R,e,t),l(e,Te,t),l(e,Q,t),l(e,fe,t),i(E,e,t),l(e,be,t),l(e,H,t),Ue=!0},p:Ne,i(e){Ue||(c(J.$$.fragment,e),c(T.$$.fragment,e),c(b.$$.fragment,e),c(h.$$.fragment,e),c($.$$.fragment,e),c(I.$$.fragment,e),c(C.$$.fragment,e),c(Z.$$.fragment,e),c(v.$$.fragment,e),c(G.$$.fragment,e),c(X.$$.fragment,e),c(Y.$$.fragment,e),c(N.$$.fragment,e),c(x.$$.fragment,e),c(R.$$.fragment,e),c(E.$$.fragment,e),Ue=!0)},o(e){m(J.$$.fragment,e),m(T.$$.fragment,e),m(b.$$.fragment,e),m(h.$$.fragment,e),m($.$$.fragment,e),m(I.$$.fragment,e),m(C.$$.fragment,e),m(Z.$$.fragment,e),m(v.$$.fragment,e),m(G.$$.fragment,e),m(X.$$.fragment,e),m(Y.$$.fragment,e),m(N.$$.fragment,e),m(x.$$.fragment,e),m(R.$$.fragment,e),m(E.$$.fragment,e),Ue=!1},d(e){e&&(a(z),a(S),a(P),a(K),a(j),a(L),a(q),a(f),a(D),a(O),a(U),a(ee),a(te),a(ae),a(g),a(le),a(se),a(oe),a(B),a(ne),a(re),a(A),a(ie),a(ce),a(me),a(W),a(pe),a(Me),a(k),a(de),a(we),a(_),a(ue),a(ye),a(Je),a(V),a(je),a(Te),a(Q),a(fe),a(be),a(H)),a(u),p(J,e),p(T,e),p(b,e),p(h,e),p($,e),p(I,e),p(C,e),p(Z,e),p(v,e),p(G,e),p(X,e),p(Y,e),p(N,e),p(x,e),p(R,e),p(E,e)}}}const He='{"title":"Treinamento distribuído com o 🤗 Accelerate","local":"treinamento-distribuído-com-o--accelerate","sections":[{"title":"Configuração","local":"configuração","sections":[],"depth":2},{"title":"Preparando a aceleração","local":"preparando-a-aceleração","sections":[],"depth":2},{"title":"Backward","local":"backward","sections":[],"depth":2},{"title":"Treinamento","local":"treinamento","sections":[{"title":"Treinamento em um Script","local":"treinamento-em-um-script","sections":[],"depth":3},{"title":"Treinamento em um Notebook","local":"treinamento-em-um-notebook","sections":[],"depth":3}],"depth":2}],"depth":1}';function ze(he){return xe(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class De extends Ve{constructor(u){super(),Re(this,u,ze,Se,_e,{})}}export{De as component}; | |
Xet Storage Details
- Size:
- 15.8 kB
- Xet hash:
- 7f645851d88321bae834df64b1494f50f1a3d7625a81c494101a62ade5051237
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.