-mpmd-absorb-inferred-fragments
قطعات ریشه، قطعات استنباط شده را جذب میکنند.
باعث میشود قطعات ریشه، قطعات استنباطشده را جذب کنند، یعنی با ادغام قطعات تولیدکننده/مصرفکننده استنباطشده در قطعات ریشه، که در آن یک قطعه ریشه هر قطعهای است که:
- یک قطعه کاربر، یا
- توسط هیچ قطعه دیگری استفاده نمیشود (مثلاً قطعهای که فقط توسط عملیات بازگشت یا انتقال استفاده میشود)، یا
- کاربر مقداری که توسط هیچ قطعه دیگری تولید شده نیست (مثلاً کاربر آرگومانهای بلوک یا انتقالها).
برای انجام این کار، مسیر از الگوهای زیر استفاده میکند تا به یک نقطه ثابت برسد:
(1) با توجه به قطعه ریشه rf ، اگر قطعه استنباطی ipf وجود داشته باشد به طوری که ipf تولیدکننده rf و rf نزدیکترین مصرف کننده ipf باشد، آنگاه ipf در rf ادغام میشود.
و به صورت دوگانه:
(2) با توجه به قطعه ریشه rf ، اگر یک مصرفکننده استنباطی icf وجود داشته باشد به طوری که icf مصرفکننده rf و rf نزدیکترین تولیدکننده icf باشد، آنگاه icf در rf ادغام میشود.
این یعنی ما ساختار/شکل برنامه را همانطور که توسط کاربر تعریف شده است، از طریق محاسبات نامگذاری شده و انتساب مرحله/مش، حفظ میکنیم.
توجه داشته باشید که این مرحله در ادغام قطعات استنباط شده کاملاً تهاجمی است و به طور خاص، میتواند باعث ایجاد تفاوتهای کوچکی در مراحل مختلف شود که میتواند تعداد قطعات منحصر به فرد برای کامپایل را افزایش دهد.
این گذر به ما هشدار میدهد که آیا توابع نهایی غیر نقطه ورودی هنوز شامل قطعات استنباط شده هستند یا خیر، زیرا این قطعات میتوانند باعث مشکلات عملکردی شوند (مثلاً انباشت گرادیان اشتباه پیش برود).
گزینهها
-absorb-on-entry-point-function : Whether to absorb inferred fragments into user-defined fragments on entry-point functions, in addition to targets of mpmd.calls.
-mpmd-call-inline
تمام عملیات mpmd.call را وارد می کند.
عملیات mpmd.call را درونخطی میکند و ویژگیهای آنها را به هر عملیات درونخطی کپی میکند.
-mpmd-copy-constants
ثابتهای تولید شده در یک قطعه کد را برای مصرفکنندگانشان کپی میکند.
ثابتها را از قطعات تولیدکنندهشان به قطعات مصرفکنندهشان کپی میکند، احتمالاً از طریق انتقال.
مثال:
%f = fragment () () {
return constant
}
%t = transfer %f
fragment (%t) (%arg) {
op(... %arg ...)
...
}
~~>
%f = fragment () () {
return constant
}
%t = transfer %f
fragment (%t) (%arg) {
%c = constant
op(... %c ...)
...
}
این میتواند برای عملکرد زمان اجرا مفید باشد: با قرار دادن ثابت در کنار کاربرانش، بهینهسازیهای بالقوه را امکانپذیر میکند و از انتقال ثابتها جلوگیری میکند. علاوه بر این، استفاده از حافظه را بهبود میبخشد: فضای مورد نیاز برای پارامترهای محاسبه را کاهش میدهیم.
-mpmd-erase-unused-callee-block-arguments
هر آرگومان بلوک فراخوانی شده mpmd را که توسط یک محاسبه (hlo) استفاده نمیشود، پاک میکند.
آرگومانهای بلوکی استفاده نشده را از توابعی که توسط mpmd.calls فراخوانی میشوند، پاک میکند. ما یک آرگومان بلوکی را در صورتی که هیچ آرگومان استفاده شدهای نداشته باشد یا فقط توسط پایانه تابع استفاده شود، یعنی اگر توسط هیچ محاسبه hlo استفاده نشود، آن را بلااستفاده در نظر میگیریم.
-mpmd-fragment-dce
آرگومانها/نتایج استفاده نشدهی قطعه کد را حذف کرده و نواحی قطعه کد را سادهسازی میکند.
آرگومانها و نتایج استفاده نشده قطعه کد را حذف میکند، در حالی که نواحی قطعه کد را سادهسازی میکند و اساساً کد MPMD مرده را از بین میبرد.
-mpmd-fragment-dedup
هرگونه عملوند تکراری را حذف میکند و منجر به قطعه قطعه شدن میشود.
هرگونه آرگومان و نتایج تکراری استفاده شده را به صورت قطعاتی حذف میکند. این کار آرگومانها و نتایج تکراری را بلااستفاده باقی میگذارد. برای حذف آرگومانها و نتایج استفاده نشده، باید مراحل دیگری اجرا شود.
-mpmd-from-unroll-to-call-counter
شمارندهی unroll مربوط به تابع attr مربوط به عملیات فراخوانی را به شمارندهی attr مربوط به فراخوانی تبدیل میکند.
هر زمان که یک عملیات فراخوانی دارای ویژگی unroll_counter باشد، این گذر آن را با ویژگی call_counter جایگزین میکند. این برای مواردی مورد نیاز است که در آنها دنبالهای از فراخوانیها از باز کردن یک حلقه در MLIR (مثلاً از طریق -mpmd-unroll-for-loops ) به جای باز کردن یک حلقه در سطح پایتون حاصل میشود.
-mpmd-merge-forward-with-backward
قطعات رو به جلو را با قطعات رو به عقب ادغام کنید.
اگر قطعهی تولیدکنندهی رو به جلو بلافاصله قبل از قطعهی مصرفکنندهی رو به عقب باشد، یک قطعهی تولیدکنندهی رو به جلو را با یک قطعهی مصرفکنندهی رو به عقب ادغام میکند. این فقط برای آخرین مرحله در زمانبندی 1F1B صادق است، بنابراین هیچ قطعهای را در مراحل قبلی ادغام نمیکند، که رفتار مورد نظر است.
-mpmd-merge-inferred-fragments
قطعات استنباط شده را با قطعات تعریف شده توسط کاربر ادغام میکند.
قطعات استنباطشده را با قطعات تعریفشده توسط کاربر یا سایر قطعات استنباطشده ادغام میکند. این مرحله برای پاکسازی/سادهسازی ماژول مفید است و میتواند پس از سایر مراحل کامپایلر که قطعات استنباطشده را معرفی میکنند، مفید باشد.
گزینهها
-merge-any-consumer : Whether to merge with any consumer or only the closest consumer.
-merge-sideways : Whether to merge with the next fragment in the same mesh (neighbor), even if not a consumer.
-mpmd-merge-transfers
مجموعههایی از انتقالها را که قطعات تولیدکننده و مصرفکننده یکسانی دارند، ادغام میکند.
مجموعههایی از انتقالهای با نوع بار مفید یکسان که قطعات تولیدکننده و مصرفکننده یکسانی دارند را ادغام میکند. مقادیر بار مفید این انتقالها عناصر کمتری از یک آستانه معین دارند، خرد نشدهاند و در pinned_host قرار نمیگیرند.
ادغام مجموعهای از انتقالها به این معنی است: الحاق مقادیر انتقالی در سایت تولیدکننده و تقسیم آنها در سایت مصرفکننده.
-mpmd-merge-user-fragments-into-scheduling-units
ادغام قطعات مبتنی بر کاربر قبل از گذر از زمانبندی خط لوله.
جفتهای قطعات تعریفشده توسط کاربر را برای استفاده همراه با مراحل زمانبندی خط لوله ادغام میکند.
-mpmd-move-transfers-to-producer
نقل و انتقالات را در کنار تولیدکنندگان آنها جابجا می کند.
انتقالها را در کنار تولیدکنندههایشان قرار میدهد: اگر عملوند یک آرگومان بلوکی است، انتقال را به ابتدای بلوک منتقل میکند، در غیر این صورت آن را پس از عملگر تعریفکننده منتقل میکند.
-mpmd-remove-transfer-cycles
چرخههای انتقال فقط دستگاه را از برنامه حذف میکند و از انتقالهای غیرضروری جلوگیری میکند.
چرخههای انتقال را حذف میکند.
مثال در نمادها:
x1 = انتقال(x0): m0 -> m1 x2 = انتقال(x1): m1 -> m2 x3 = انتقال(x2): m2 -> m3 x0_1 = انتقال(x3): m3 -> m0 x1_1 = انتقال(x0_1): m0 -> m1
~~>
x1 = انتقال(x0): m0 -> m1 x2 = انتقال(x1): m1 -> m2 x3 = انتقال(x2): m2 -> m3 x0_1 = x0 x1_1 = x1
یعنی ما با استفاده از مقادیر موجود، چرخه را میشکنیم و انتقالهای غیرضروری را حذف میکنیم.
توجه داشته باشید که این میتواند سربار حافظه را افزایش دهد، زیرا انتقال دادهها به بیرون و دوباره به این معنی است که دورهای وجود دارد که دادهها روی دستگاه نیستند. بنابراین، ما فقط در صورتی این کار را انجام میدهیم که چرخه فقط شامل انتقال دستگاه به دستگاه باشد، مثلاً از آنجا که یک چرخه device -> host -> device میتواند برای اهداف حافظه باشد.
این از کانونیکالایزر MLIR استفاده نمیکند، زیرا این تضمین نمیکند که همه چیز کانونیکال شده باشد، و همچنین اعمال آن گرانتر است.
-mpmd-rule-based-merge
قطعات را بر اساس قوانین تعریف شده توسط کاربر ادغام میکند.
قطعات را بر اساس فهرست مشخصی از قوانین ادغام میکند، که هر کدام فهرستی از قطعات منبع برای ادغام (با اطلاعات قطعه آنها) و اطلاعات هدف برای برچسبگذاری قطعه ادغامشده را مشخص میکنند.
گزینهها
-rules : A list of fragment merge rules, each with a list of source fragment infos and a target fragment info.
-remove-control-dependencies : Whether to remove control dependencies at the end of the pass.
-mpmd-scheduling-units-verifier
بررسی میکند که آیا برنامه شامل واحدهای زمانبندی مورد نیاز است یا خیر.
-mpmd-sink-negligible-ops-into-call-op
عملیاتهای ناچیز را در توابع فراخوانی (یعنی تابع فراخوانیشده) قرار میدهد.
عملیات (ناچیز) را در توابع فراخوانی شده غرق میکند: اگر عملیاتی با صفر عملوند و یک نتیجه واحد وجود داشته باشد که به عنوان یک عملوند خاص از همه عملیات فراخوانی به همان تابع استفاده میشود، آن را در آن عملیات فراخوانی فرو میکنیم، یعنی آن را در تابع فراخوانی شده کلون میکنیم و تمام کاربردهای آرگومان مربوطه را با کلون جایگزین میکنیم. عملیاتهای غرق شده از تابع فراخوانی کننده حذف میشوند و آرگومانهای استفاده نشده از فراخوانی شونده (و عملوندهای عملیات فراخوانی مربوطه) حذف میشوند. توجه داشته باشید که این امر میتواند به طور بالقوه محاسبات را در بسیاری از ریزدستهها، هنگام استفاده از عملیات فراخوانی برای ریزدستهبندی، تکرار کند. اگرچه، این محاسبه به احتمال زیاد ناچیز است زیرا هیچ عملوندی نمیگیرد.
-mpmd-split-and-prioritize-transfer-independent-computations
قطعات رو به عقب را بر اساس نتایج منتقل شده تقسیم میکند.
یک قطعه را به دو قطعه تقسیم میکند تا بتوانیم محاسبه را زودتر شروع کنیم. یعنی قطعه را به دو قطعه A -> B تقسیم میکنیم، که در آن A به هیچ نتیجه انتقالی متکی نیست و حداکثر بزرگ است و B به نتایج انتقال متکی است.
-mpmd-split-bwd-fragments
قطعات رو به عقب را بر اساس نتایج منتقل شده تقسیم میکند.
قطعات را به عقب تقسیم میکند تا هر محاسبهای که به نتایج منتقلشده جریان پیدا نکند، به قطعهای از خودش تبدیل شود. قطعه اصلی برخی از مقادیر باقیمانده را برمیگرداند که به عنوان عملوندهای اضافی به قطعات جدا شده منتقل میشوند.
این تقسیمبندی به ما امکان میدهد نتایج را زودتر به مشهای دیگر منتقل کنیم. یکی از کاربردهای متعارف این بهینهسازی، تقسیم محاسبه گرادیان فعالسازی در پسانتشار از محاسبه گرادیان پارامتر خواهد بود. همچنین توجه داشته باشید که به دلیل نیاز به پیمایش بالقوه برخی از مقادیر باقیمانده در قطعات جدید، فشار حافظه افزایش مییابد.
-mpmd-uniquify-function-inputs-outputs
هر مقداری که چندین بار برگردانده شود یا هر آرگومان بلوکی که مستقیماً توسط تابع برگردانده شود را یونیک میکند.
اگر یک تابع چندین بار مقدار یکسانی را برگرداند، با ایجاد یک قطعه اختصاص داده شده به مش آن مقدار که چندین بار مقدار را برمیگرداند، نسخههای متعددی برای آن مقدار ایجاد میکند. پس از این مرحله، هر عملوند بازگشتی منحصر به فرد است. این مهم است تا اطمینان حاصل شود که نتایج مربوطه در بافرهای مختلف تخصیص داده میشوند، مانند مثال jax.jit زیر:
def f(x):
y = x + x
return y, y
z1, z2 = f(5)
z1 += 1
print(z1) ~~> 6
print(z2) ~~> 5
به طور مشابه، اگر تابعی یک آرگومان بلوکی را برگرداند، این ارسال، یک قطعه هویت برای آن آرگومان بلوکی ایجاد میکند و تضمین میکند که مقادیر به صورت مقداری به تابع ارسال میشوند، نه به صورت ارجاعی.
گزینهها
-use-transfer-instead-of-fragment : Whether to use mpmd.transfer or mpmd.fragment for uniquification
-mpmd-unroll-for-loops
حلقههای mpmd.for به طور کامل باز میکند.
مسیری ایجاد میکند که mpmd.for عملیات را به طور کامل باز میکند، در حالی که یک ویژگی unroll_counter را به هر عملیات باز شده متصل میکند.
لازم است: ضریب باز شدن برابر با تعداد تکرارها باشد.
-mpmd-verify-stage-merging
تأیید میکند که ادغام قطعات اختصاص داده شده به مراحل با موفقیت انجام شده است.
تأیید میکند که قطعات دارای تخصیص مرحلهای به درستی ادغام شدهاند. این بدان معناست که امکان ندارد دو قطعه معادل از نظر تخصیص و شمارندهها در ماژول وجود داشته باشد.
دو قطعه از نظر انتساب و شمارندهها معادل هستند اگر الف) به یک مش اختصاص داده شده باشند، ب) به یک مرحله اختصاص داده شده باشند، ج) تعداد ترانهاده یکسانی داشته باشند، و د) یا هر دو شمارنده فراخوانی یکسانی داشته باشند یا یکی از آنها شمارنده فراخوانی تعریف شده نداشته باشد (یعنی یک شمارنده فراخوانی تعریف نشده با هر شمارنده فراخوانی مطابقت داشته باشد).
این امر برای تضمین این امر به کاربر ضروری است که هر محاسبهای که به یک مرحله اختصاص داده شده است، به صورت پیوسته اجرا شود.