MarkTechPostآخر تحديث

ميتا تُتيح كود Rebalancer الخاص بالذكاء الاصطناعي كمصدر مفتوح: حلّاس مهام بلغة C++ يعالج نحو 40 مليون مسألة توزيع يوميًا

أطلقت ميتا مكتبة Rebalancer كمصدر مفتوح، وهي مكتبة بلغتي C++ وPython التي استخدمتها لأكثر من 9 سنوات لتوزيع الأجزاء (shards) والخوادم وحركة المرور. تعالج المكتبة نحو 40 مليون مسألة إسناد يوميًا، باستخدام البحث المحلي أو…

لقد أصدرت Meta كمصدر مفتوح Rebalancer، وهي مكتبة بلغة C++ مع واجهة بايثون لحل مسائل الإسناد. وهي تقرر أي الكائنات توضع في أي الحاويات وفق قيود وأهداف. وفقًا لـ منشور فريق الهندسة في ميتا، يعمل Rebalancer على إدارة تخصيص الموارد عبر Meta منذ أكثر من 9 سنوات. تم إطلاق المشروع بموجب ترخيص Apache 2.0 مع التوثيق، حزمة PyPI وأداة واجهة مستخدم لتصحيح الأخطاء تُسمى Rebalancer Explorer.

هل يمكن نشره؟ نعم. pip install rebalancer يقوم بتثبيت v1.0.4 لـ Python 3.12 وما فوق، مع حزم wheels جاهزة مسبقًا لـ Linux x86-64 وmacOS 14+ ARM64. وتتوفر أيضًا حزم ‎.deb و.rpm وHomebrew. ولا يزال PyPI يصنّف المشروع كإصدار Alpha.

ما المشكلة التي يحلّها Rebalancer؟

تظهر مسائل الإسناد في مختلف أنحاء بنية Meta التقنية. الرفوف تُوضع في مراكز البيانات، والخوادم تُخصص للخدمات، والمهام تُوزع على الخوادم، وحركة مرور المستخدمين تُوجَّه إلى مراكز البيانات. تذكر Meta عقبتين: 2 من العوائق، وهما قابلية الاستخدام وقابلية التوسع. يواجه المهندسون صعوبة في تحويل السياسات إلى صيغ دقيقة، وكثير من المسائل من فئة NP-hard وكبيرة جداً بالنسبة للحلول التجارية.

يجيب Rebalancer بفصل طريقة تحديد المسألة عن طريقة حلها. يتم تفصيل التصميم في ورقة OSDI 2024, تحسين تخصيص الموارد في مراكز البيانات فائقة النطاق.

كيف تعمل طبقة التحديد

لغة التحديد تتكون من 3 طبقات:

  • بنى النمذجة: الأبعاد (خصائص مثل وحدة المعالجة المركزية أو التخزين)، والأقسام (مجموعات من الكائنات)، والنطاقات (مجموعات من الصناديق) والاستخدام.
  • واجهة برمجة التطبيقات للتعبيرات: تجميع الاستخدام باستخدام SUM أو MAX، أو تحويله بعمليات مثل SQUARE.
  • واجهة برمجة التطبيقات للتحديد: عشرات الأهداف والقيود المعرّفة مسبقاً، مدرجة في الوثائق.

في مثال Meta، تُنمذج المهام ككائنات، والخوادم كصناديق، والرفوف كنطاق. قيدٌ CapacitySpec يحد من وحدة المعالجة المركزية والتخزين لكل خادم. قيدٌ GroupCountSpec يحافظ على 1 نوع وظيفة لكل رف. قيدٌ BalanceSpec يوازن استخدام كل خادم عبر البعدين معًا.

مخطط تعبير واحد، وحلّان

يُجمِّع Rebalancer المواصفات في مخطط تعبيري موجَّه غير دوري. تحتوي العقد الطرفية على قيم الاستخدام؛ وتقع عقد التجميع والتحويل فوقها. يقدّم المستخدمون تعيينًا أوليًا وشرط توقّف. وتصبح القيود التي ينتهكها التعيين الأولي بالفعل أهدافًا عالية الأولوية.

الحل الأمثل: تتم ترجمة المخطط البياني إلى برنامج أعداد صحيحة مختلط من أجل FICO Xpress, Gurobi أو HiGHS. يؤدي تجميع المتغيرات وكسر التناظر إلى تقليص حجم النماذج. يبقى حجم النموذج في أسوأ الحالات بحد O(objects × bins). مشكلات Meta الأكبر حجمًا أكبر من قدرة أي من حَلّ MIP.

البحث المحلي: يعمل هذا الحَلّ مباشرة على رسم التعبير. يستكشف نقل الكائنات إلى صناديق أخرى، بحيث يبلغ حجم الجوار في أسوأ الحالات O(objects + bins). ثم يطبّق أفضل مرشّح لا يخالف أي قيد. يتم موازَنة التقييم لتحقيق ملايين التقييمات في الثانية، مع تقليم فضاء البحث.

تستخدم Meta البحث المحلي لمعظم المشكلات الكبيرة وحَلّ MIP للمشكلات الصغيرة إلى متوسطة الحجم، وغالبًا ما تبدأ بوضع نموذج أولي باستخدام MIP.

أرقام الإنتاج في Meta

  • نحو 40 مليون مسألة تعيين تُحَلّ يوميًا، عبر أكثر من 30 صياغة فريدة.
  • زمن الحل عند المئين 99 هو 12 ثانية على 265k كائن و3.2k صندوق.
  • المسائل التي تتجاوز 1 مليون كائن و5k صندوق يبلغ متوسط زمن حلّها 171 ثانية، عبر 3.4k+ تشغيل.

أفضل حالات الاستخدام لـ Rebalancer

  1. وضع الشرائح أو المهام أو الحاويات على عنقود: إسناد العمل إلى الخوادم في ظل حدود لوحدة المعالجة المركزية والذاكرة مع توزيع النسخ المتماثلة على الحوامل (racks). تعمل أنظمة Meta التالية على هذا النمط: Shard Manager و RAS موازنة حركة المرور وأعباء العمل عبر المناطق
  2. : توجيه حركة مرور المستخدمين أو المهام إلى مراكز البيانات، مع الموازنة بين زمن الاستجابة والحمل.يحقق Taiji هذا لحركة المرور الطرفية، كما توازن Meta تدريب تعلّم الآلة حسب الأولوية.
  3. تعيين عمليات خارج البنية التحتية: مطابقة تذاكر الدعم بالمهندسين، والاجتماعات بالغرف، أو المكاتب بالأشخاص وفق قواعد السعة. وقد قامت Meta بالأمور الـ3 جميعها.

تصحيح الأخطاء باستخدام Rebalancer Explorer

أمضى المصممون النماذجيون في Meta معظم وقتهم في تصحيح سلوك الحلّال. Rebalancer Explorer هو واجهة ويب مغلّفة بـ Docker بُنيت لهذا الغرض. وهي تعرض القيود المقيّدة، وآثار التخفيف، وسبب وصول كائن ما إلى حاوية معينة.

شرح تفاعلي

Run local search</button> <button class="b" id="mtpStep">Step once</button> <button class="b" id="mtpShuf">Random bad start</button> <button class="b" id="mtpReset">Reset</button> </div> <div class="stats"> <div class="st"><div class="k">Step</div><div class="v" id="mtpS">0</div></div> <div class="st"><div class="k">Moves evaluated</div><div class="v" id="mtpE">0</div></div> <div class="st"><div class="k">Capacity overflow</div><div class="v" id="mtpV">0</div></div> <div class="st"><div class="k">Balance objective</div><div class="v" id="mtpO">0</div></div> </div> <div class="racks" id="mtpRacks"></div> <div class="spark"><div class="k">Objective over steps (lower is better, ideal = 324)</div> <svg id="mtpSpark" viewBox="0 0 800 70" width="100%" height="70" preserveAspectRatio="none"></svg> </div> <div class="log" id="mtpLog">Server S1 starts 4 CPU over capacity. Press Run.</div> </div> <!-- PANE 2 --> <div class="pane" id="mtpP1"> <p class="note">يحوّل Rebalancer المواصفات إلى <b>رسم بياني موجّه غير دوري للتعبيرات</b>. تحتفظ الأوراق باستغلال كل خادم، وتجلس عقد SQUARE وSUM وMAX فوقها. عندما ينتقل مهمة واحدة، لا تحتاج إلا الأوراق التي تلمسها وأسلافها إلى قيم جديدة. يستخدم الرسم البياني الحالة الحية نفسها الموجودة في التبويب 1.</p> <div class="btns"> <button class="b pri" id="mtpGMove">Move a random task</button> <button class="b" id="mtpGBest">Apply best local-search move</button> </div> <div class="gwrap"><svg id="mtpGraph" viewBox="0 0 820 300" width="100%"></svg></div> <div class="log" id="mtpGLog">Press a button to move a task.</div> </div> <!-- PANE 3 --> <div class="pane" id="mtpP2"> <p class="note">يحتاج نموذج MIP إلى نحو متغير ثنائي واحد لكل كائن لكل حاوية، لذا ينمو بمقدار <b>O(objects × bins)</b>. أما جوار البحث المحلّي فينمو بمقدار <b>O(objects + bins)</b>. اسحب أشرطة التمرير أو حمّل الأحجام التي نشرتها Meta.</p> <div class="btns"> <button class="b" data-o="500" data-bn="20">Small: 500 × 20</button> <button class="b" data-o="265000" data-bn="3200">Meta P99: 265k × 3.2k</button> <button class="b" data-o="1000000" data-bn="5000">Meta XL: 1M × 5k</button> </div> <div class="sl"><label>Objects <b id="mtpOv"></b></label><input type="range" id="mtpOs" min="1" max="6.3" step="0.01" value="2.7"></div> <div class="sl"><label>Bins <b id="mtpBv"></b></label><input type="range" id="mtpBs" min="0.3" max="4" step="0.01" value="1.3"></div> <div class="cmp"> <div class="row"><div class="t">MIP binary variables, worst case <span id="mtpMv"></span></div><div class="track"><i id="mtpMb" style="background:linear-gradient(90deg,#FF8A5A,#FF5A6E)"></i></div></div> <div class="row"><div class="t">Local-search neighborhood, worst case <span id="mtpLv"></span></div><div class="track"><i id="mtpLb" style="background:linear-gradient(90deg,#0866FF,#38D6FF)"></i></div></div> </div> <div class="verdict" id="mtpVerdict"></div> <p class="note" style="margin-top:10px">تستخدم الأشرطة مقياساً لوغاريتمياً. نطاقات الأحجام في الحكم توضيحية؛ فالقاعدة المعلنة من Meta هي استخدام البحث المحلّي لجميع المشكلات الكبيرة تقريباً، وMIP للمشكلات الصغيرة إلى متوسطة الحجم.</p> </div> <!-- PANE 4 --> <div class="pane" id="mtpP3"> <p class="note">أرقام الإنتاج المنشورة من Meta عن Rebalancer (Engineering at Meta، 21 سبتمبر 2026).</p> <div class="grid" id="mtpCards"> <div class="card"><div class="n"><span data-c="40">0</span><em>M</em></div><div class="d">مسألة توزيع يتم حلها يوميًا</div></div> <div class="card"><div class="n"><span data-c="30">0</span><em>+</em></div><div class="d">صيغة فريدة للمسائل</div></div> <div class="card"><div class="n"><span data-c="12">0</span><em>s</em></div><div class="d">زمن الحل عند P99 على 265k عنصر و3.2k حاوية</div></div> <div class="card"><div class="n"><span data-c="171">0</span><em>s</em></div><div class="d">متوسط زمن الحل لأكثر من 1M عنصر و5k حاوية</div></div> <div class="card"><div class="n"><span data-c="3.4" data-d="1">0</span><em>k+</em></div><div class="d">تشغيل على ذلك الحجم الذي يزيد عن 1M عنصر</div></div> <div class="card"><div class="n"><span data-c="9">0</span><em>+ yrs</em></div><div class="d">سنة من الاستخدام عبر Meta قبل إتاحته كمصدر مفتوح</div></div> </div> <div class="pills"> <span class="pill">Shard Manager: الأجزاء ← الخوادم</span> <span class="pill">RAS: الخوادم ← الخدمات</span> <span class="pill">Taiji: حركة الحافة ← مراكز البيانات</span> <span class="pill">تجميع دوال Serverless</span> <span class="pill">موازنة تدريب التعلم الآلي</span> <span class="pill">الاجتماعات ← القاعات</span> </div> </div> <div class="ft"> <span>المصادر: <a href="https://engineering.fb.com/2026/09/21/open-source/rebalancer-generic-high-performance-library-assignment-problems/" target="_blank" rel="noopener">Engineering at Meta</a> · <a href="https://github.com/facebook/rebalancer" target="_blank" rel="noopener">GitHub</a> · التبويبات من 1 إلى 3 محاكاة مبسّطة</span> <span class="brand">صُنع بواسطة Marktechpost</span> </div> </div> <script> (function(){ var R=document.getElementById('mtp-rebal'); function postH(){try{parent.postMessage({mtpRebalH:R.offsetHeight+40},'*');}catch(e){}} var SIZES=[6,5,4,4,3,3,3,2,2,2,1,1], CAP=16, NS=4; var START=[0,0,0,0,1,1,1,2,2,2,0,1]; var asg=START.slice(), step=0, evals=0, hist=[], timer=null, hot=-1; function util(a){var u=[0,0,0,0];for(var i=0;i<a.length;i++)u[a[i]]+=SIZES[i];return u;} function score(a){var u=util(a),v=0,o=0;for(var s=0;s<NS;s++){v+=Math.max(0,u[s]-CAP);o+=u[s]*u[s];}return [v,o];} function better(x,y){return x[0]<y[0]||(x[0]===y[0]&&x[1]<y[1]);} function bestMove(){ var cur=score(asg),best=null,bs=cur,n=0; for(var i=0;i<asg.length;i++){for(var s=0;s<NS;s++){if(s===asg[i])continue;var b=asg.slice();b[i]=s;n++;var sc=score(b);if(better(sc,bs)){bs=sc;best={a:b,txt:'move t'+(i+1)+' S'+(asg[i]+1)+' → S'+(s+1),ids:[i]};}}} for(var i2=0;i2<asg.length;i2++)for(var j=i2+1;j<asg.length;j++){if(asg[i2]===asg[j])continue;var c=asg.slice();c[i2]=asg[j];c[j]=asg[i2];n++;var sc2=score(c);if(better(sc2,bs)){bs=sc2;best={a:c,txt:'swap t'+(i2+1)+' t'+(j+1),ids:[i2,j]};}} return {best:best,n:n,sc:bs}; } var racksEl=document.getElementById('mtpRacks'); function rects(){var m={};racksEl.querySelectorAll('.chip').forEach(function(c){m[c.dataset.id]=c.getBoundingClientRect();});return m;} function render(ids){ var before=rects(),u=util(asg),h=''; for(var r=0;r<2;r++){h+='<div class="rack"><div class="rl">رف '+(r?'B':'A')+' (النطاق)</div><div class="srvs">'; for(var s=r*2;s<r*2+2;s++){var over=u[s]>CAP; h+='<div class="srv'+(over?' over':'')+'"><div class="sn">S'+(s+1)+'<span>'+u[s]+' / '+CAP+' CPU</span></div><div class="bar"><i style="width:'+Math.min(100,u[s]/24*100)+'%"></i><u style="left:'+(CAP/24*100)+'%"></u></div><div class="chips">'; for(var i=0;i<asg.length;i++)if(asg[i]===s){h+='<div class="chip'+(ids&&ids.indexOf(i)>-1?' hot':'')+'" data-id="'+i+'" style="width:'+(30+SIZES[i]*8)+'px">t'+(i+1)+'·'+SIZES[i]+'</div>';} h+='</div></div>';} h+='</div></div>';} racksEl.innerHTML=h; racksEl.querySelectorAll('.chip').forEach(function(c){var b=before[c.dataset.id];if(!b)return;var a=c.getBoundingClientRect(),dx=b.left-a.left,dy=b.top-a.top;if(dx||dy){c.style.transition='none';c.style.transform='translate('+dx+'px,'+dy+'px)';requestAnimationFrame(function(){requestAnimationFrame(function(){c.style.transition='transform .55s cubic-bezier(.2,.8,.2,1)';c.style.transform='';});});}}); var sc=score(asg); document.getElementById('mtpS').textContent=step; document.getElementById('mtpE').textContent=evals; var V=document.getElementById('mtpV');V.textContent=sc[0];V.className='v '+(sc[0]?'bad':'good'); var O=document.getElementById('mtpO');O.textContent=sc[1];O.className='v'+(sc[1]===324?' good':''); spark();drawGraph(null);postH(); } function spark(){ var s=document.getElementById('mtpSpark'),pts=hist.length?hist:[score(asg)[1]]; var mx=Math.max.apply(null,pts.concat([600])),mn=300,n=Math.max(pts.length-1,12); var p=pts.map(function(v,i){return (i/n*790+5)+','+(65-(v-mn)/(mx-mn)*58);}).join(' '); var ideal=65-(324-mn)/(mx-mn)*58; s.innerHTML='<line x1="0" x2="800" y1="'+ideal+'" y2="'+ideal+'" stroke="#2BD99F" stroke-dasharray="4 4" opacity=".6"/><polyline points="'+p+'" fill="none" stroke="#38D6FF" stroke-width="2.5"/>'+pts.map(function(v,i){return '<circle cx="'+(i/n*790+5)+'" cy="'+(65-(v-mn)/(mx-mn)*58)+'" r="3.5" fill="#0866FF" stroke="#fff" stroke-width="1"/>';}).join(''); } var logEl=document.getElementById('mtpLog'); function doStep(){ var r=bestMove();evals+=r.n; if(!r.best){stop();logEl.textContent='الحد الأمثل المحلي: لا يوجد نقل أو تبديل يحسّن النتيجة ('+evals+' تقييمًا).';render();return false;} var old=asg;asg=r.best.a;step++;hist.push(score(asg)[1]); var moved=r.best.ids;logEl.textContent='الخطوة '+step+': '+r.best.txt+' (تم فحص '+r.n+' مرشحًا)'; render(moved);drawGraph(diff(old,asg));return true; } function diff(a,b){var s={};for(var i=0;i<a.length;i++)if(a[i]!==b[i]){s[a[i]]=1;s[b[i]]=1;}return Object.keys(s).map(Number);} function stop(){if(timer){clearInterval(timer);timer=null;}document.getElementById('mtpRun').textContent=' تشغيل البحث المحلي';} document.getElementById('mtpRun').onclick=function(){if(timer){stop();return;}this.textContent='❚❚ إيقاف مؤقت';if(!doStep())return;timer=setInterval(function(){if(!doStep())stop();},900);}; document.getElementById('mtpStep').onclick=function(){stop();doStep();}; function resetTo(a,msg){stop();asg=a;step=0;evals=0;hist=[score(asg)[1]];logEl.textContent=msg;render();} document.getElementById('mtpReset').onclick=function(){resetTo(START.slice(),'الخادم S1 يبدأ بـ 4 CPU فوق السعة. اضغط تشغيل.');}; document.getElementById('mtpShuf').onclick=function(){var a=[];for(var i=0;i<12;i++)a.push(Math.random()<.55?Math.floor(Math.random()*2):Math.floor(Math.random()*4));resetTo(a,'بداية عشوائية جديدة. اضغط تشغيل.');}; /* مخطط التعبير */ var G=document.getElementById('mtpGraph'),gLog=document.getElementById('mtpGLog'); var LX=[110,300,490,680]; function drawGraph(live){ live=live||[];var u=util(asg),sc=score(asg),h=''; function on(s){return live.indexOf(s)>-1;} var any=live.length>0; for(var s=0;s<4;s++){ h+='<path class="edge'+(on(s)?' live':'')+'" d="M'+LX[s]+',232 L'+LX[s]+',172"/>'; h+='<path class="edge'+(on(s)?' live':'')+'" d="M'+LX[s]+',138 C'+LX[s]+',100 300,110 300,78"/>'; h+='<path class="edge'+(on(s)?' live':'')+'" d="M'+(LX[s]+40)+',233 C'+(LX[s]+60)+',200 650,130 650,78"/>'; } h+='<path class="edge'+(any?' live':'')+'" d="M300,44 L300,22"/><path class="edge'+(any?' live':'')+'" d="M650,44 L650,22"/>'; function node(x,y,w,label,val,l){return '<g class="node'+(l?' live':'')+'"><rect x="'+(x-w/2)+'" y="'+(y-17)+'" width="'+w+'" height="34" rx="8"/><text x="'+x+'" y="'+(y-2)+'">'+label+'</text><text class="val" x="'+x+'" y="'+(y+11)+'">'+val+'</text></g>';} for(var k=0;k<4;k++){h+=node(LX[k],250,96,'U(S'+(k+1)+')','= '+u[k],on(k));h+=node(LX[k],155,96,'SQUARE','= '+u[k]*u[k],on(k));} h+=node(300,61,120,'SUM','= '+sc[1],any);h+=node(650,61,120,'MAX','= '+Math.max.apply(null,u),any); h+='<text x="300" y="14" fill="#4C9BFF" font-size="11" font-weight="700" text-anchor="middle">هدف BalanceSpec</text>'; h+='<text x="650" y="14" fill="'+(Math.max.apply(null,u)>CAP?'#FF5A6E':'#2BD99F')+'" font-size="11" font-weight="700" text-anchor="middle">CapacitySpec: MAX ≤ '+CAP+(Math.max.apply(null,u)>CAP?' (مخالفة)':' (سليم)')+'</text>'; h+='<text x="410" y="292" fill="#93A3BF" font-size="11" text-anchor="middle">الأوراق: الاستخدام لكل خادم · العقد المُعاد حسابها في هذه الحركة: '+(any?(live.length*2+2):0)+' من أصل 10</text>'; G.innerHTML=h; } document.getElementById('mtpGMove').onclick=function(){stop();var i=Math.floor(Math.random()*12),s;do{s=Math.floor(Math.random()*4);}while(s===asg[i]);var old=asg;asg=asg.slice();asg[i]=s;evals++;step++;hist.push(score(asg)[1]);render([i]);var d=diff(old,asg);drawGraph(d);gLog.textContent='Moved t'+(i+1)+' S'+(old[i]+1)+' → S'+(s+1)+'. Only '+(d.length*2+2)+' of 10 nodes needed new values.';}; document.getElementById('mtpGBest').onclick=function(){stop();var r=bestMove();evals+=r.n;if(!r.best){gLog.textContent='Local optimum reached. Try a random move first.';render();return;}var old=asg;asg=r.best.a;step++;hist.push(score(asg)[1]);render(r.best.ids);var d=diff(old,asg);drawGraph(d);gLog.textContent='Best of '+r.n+' candidates: '+r.best.txt+'. Recomputed '+(d.length*2+2)+' of 10 nodes.';}; /* solver picker */ var Os=document.getElementById('mtpOs'),Bs=document.getElementById('mtpBs'); function fmt(n){if(n>=1e9)return (n/1e9).toFixed(n>=1e10?0:1)+'B';if(n>=1e6)return (n/1e6).toFixed(n>=1e7?0:1)+'M';if(n>=1e3)return (n/1e3).toFixed(n>=1e4?0:1)+'k';return Math.round(n)+'';} function pick(){ var o=exactO||Math.round(Math.pow(10,+Os.value)),b=exactB||Math.round(Math.pow(10,+Bs.value)),m=o*b,l=o+b;exactO=exactB=0; document.getElementById('mtpOv').textContent=fmt(o);document.getElementById('mtpBv').textContent=fmt(b); document.getElementById('mtpMv').textContent='≈ '+fmt(m);document.getElementById('mtpLv').textContent='≈ '+fmt(l); document.getElementById('mtpMb').style.width=Math.min(100,Math.log10(m)/11*100)+'%'; document.getElementById('mtpLb').style.width=Math.min(100,Math.log10(l)/11*100)+'%'; var v=document.getElementById('mtpVerdict'),t; if(m<=1e6){t='<b>حلّاء MIP الأمثل بداية جيدة.</b> نموذج صغير: سلّمه إلى HiGHS أو Gurobi أو FICO Xpress واحصل على إسناد مثبت الأمثلية.';v.style.borderColor='#2BD99F';} else if(m<=1e8){t='<b>جرّب أولًا باستخدام MIP، ثم انتقل إلى البحث المحلي.</b> تقول Meta إن هذا مسار شائع: اعثر على خط أساس قوي باستخدام الحلّاء الأمثل، ثم انتقل.';v.style.borderColor='#4C9BFF';} else{t='<b>البحث المحلي.</b> سيحتاج نموذج MIP إلى ≈ '+fmt(m)+' متغيرًا ثنائيًا في ال worst case, while each local-search neighborhood stays near '+fmt(l)+'. تشغّل Meta تقريبًا كل المسائل الكبيرة بهذه الطريقة.';v.style.borderColor='#38D6FF';} v.innerHTML=t;postH(); } var exactO=0,exactB=0;Os.oninput=pick;Bs.oninput=pick; document.querySelectorAll('#mtpP2 button[data-o]').forEach(function(btn){btn.onclick=function(){exactO=+btn.dataset.o;exactB=+btn.dataset.bn;Os.value=Math.log10(+btn.dataset.o);Bs.value=Math.log10(+btn.dataset.bn);pick();};}); /* stats */ var counted=false; function count(){ var cards=document.querySelectorAll('#mtpCards .card'); cards.forEach(function(c,i){c.classList.remove('in');setTimeout(function(){c.classList.add('in');},90*i);}); document.querySelectorAll('#mtpCards [data-c]').forEach(function(el){var tgt=+el.dataset.c,dp=+(el.dataset.d||0),t0=null; function f(ts){if(!t0)t0=ts;var p=Math.min(1,(ts-t0)/1100),e=1-Math.pow(1-p,3);el.textContent=(tgt*e).toFixed(dp);if(p<1)requestAnimationFrame(f);}requestAnimationFrame(f);}); } /* tabs */ var tabs=R.querySelectorAll('.tab'); tabs.forEach(function(t){t.onclick=function(){tabs.forEach(function(x){x.classList.remove('on');});t.classList.add('on'); R.querySelectorAll('.pane').forEach(function(p){p.classList.remove('on');});document.getElementById('mtpP'+t.dataset.p).classList.add('on'); if(t.dataset.p==='3')count();if(t.dataset.p==='1')drawGraph(null);setTimeout(postH,60);setTimeout(postH,450);};}); hist=[score(asg)[1]];render();pick(); window.addEventListener('load',postH);window.addEventListener('resize',postH);setTimeout(postH,300); })(); </script> </body></html>">

أداة Rebalancer من Meta مقابل أقرب البدائل مفتوحة المصدر

الميزةMeta RebalancerGoogle OR-ToolsTimefold Solver (النسخة المجتمعية)
الترخيصApache 2.0Apache 2.0Apache 2.0 (إصدار المؤسسات تجاري)
اللغة الأساسيةC++C++Java
واجهات البرمجةC++، PythonC++، Python، Java، C#Java، Kotlin
التركيزإسناد عام (كائنات إلى حاويات)حزمة واسعة: CP-SAT، أغلفة LP وMIP، التوجيه، التعبئة، الإسنادالتخطيط: التوجيه، الجدولة الوردية، الجدولة الزمنية، إسناد المهام
البحث المحلينعم، بالتوازي، على مخطط التعبيراتنعم، في محلّل التوجيه (البحث المحلي الموجَّه، محاكاة التلدين، البحث المحظور)نعم، المحرك الأساسي (البحث المحظور، محاكاة التلدين، القبول المتأخر)
أنظمة MIP الخلفيةFICO Xpress وGurobi وHiGHSأغلفة لمحلّلي MIP التجاريين ومفتوحي المصدرغير مستخدم
تصحيح أخطاء واجهة المستخدممستكشف المُوازِن (Docker)غير مذكور في READMEأداة قياس أداء (Benchmarker)؛ تحليل النتائج في الإصدارات التجارية
التثبيتpip install rebalancerpip install ortoolsMaven، وJDK 21 وما فوق

تغطي OR-Tools فئات مسائل أكثر، ويستهدف Timefold الجدولة والتوجيه على JVM. تتميز Rebalancer بمواصفة إسناد واحدة تعمل على كل من البحث المحلي وMIP.

النقاط الرئيسية

  • تصمّم Rebalancer أي مسألة إسناد باستخدام الكائنات والحاويات والقيود والأهداف.
  • تُترجم المواصفات إلى رسم بياني للتعبيرات يُحل بواسطة البحث المحلي أو محلّل MIP.
  • تشمل أنظمة MIP الخلفية FICO Xpress وGurobi وHiGHS مفتوح المصدر.
  • تُشغِّل Meta حوالي 40M مشكلة يوميًا؛ إذ يبلغ زمن P99 هو 12s على 265k من العناصر و3.2k من الصناديق.
  • ترخيص Apache 2.0، وواجهات برمجية بلغة C++ وPython، وقابل للتثبيت من PyPI اليوم.


اطلع على الورقة البحثية, مستودع GitHub و التفاصيل التقنية. كل الفضل يذهب إلى باحث هذا المشروع. كما لا تترددوا في متابعتنا على تويتر ولا تنسوا الانضمام إلى مجتمع 150k+ML SubReddit والاشتراك في نشرتنا البريدية. مهلاً! هل أنت على تيليجرام؟ يمكنك الآن الانضمام إلينا على تيليجرام أيضاً.

[بدعم] الويب هو الواجهة البرمجية الوحيدة التي يفتقر إليها معظم الوكلاء. قواعد البيانات والتقويمات والمستودعات لها واجهات برمجية، بينما الويب المفتوح في معظمه لا يملكها. خادم TinyFish MCP يمنح أي عميل MCP أربع أدوات: TinySearch وTinyFetch (صفحات كاملة بصيغة markdown بما فيها JavaScript) وTinyBrowser لتسجيل الدخول والنماذج، وTinyAgent للمهام متعددة الخطوات. البحث والجلب مجانيان.

ظهر المقال ميتا AI تفتح مصدر Rebalancer: محلّل إسناد بلغة C++ يشغّل حوالي 40 مليون مسألة توظيف يومياً أولاً على MarkTechPost.

المصدر الأصلي

MarkTechPost

ملاحظات المحتوى

النشر الأصلي والحقوق تعود إلى المصدر.

ترجمة آلية · يُرجى الرجوع إلى الأصل