PDA

View Full Version : inline function



JalaliMehr
چهارشنبه 22 آذر 1391, 13:40 عصر
سلام
چه وقت بایستی تابع inline باشه و چه مواقعی نباشه و کلاً inline بودن توابع چه مزیتی داره؟
تشکر

hadi0x7c7
چهارشنبه 22 آذر 1391, 19:26 عصر
تابع inline مثل macro میمونه و شما سربار صدا زدن تابع رو نداری.
مثلا اگه تو یه حلقه که 100000 بار اجرا میشه و شما یه تابع توی اون صدا میزنی . بهتر تابع که درون اون استفاده میشه inline باشه تا هر بار تابع صدا زده نشه و فقط یک سری statement اجرا بشن که به طبع سریع تره.

mehdi.mousavi
چهارشنبه 22 آذر 1391, 20:27 عصر
سلام چه وقت بایستی تابع inline باشه و چه مواقعی نباشه و کلاً inline بودن توابع چه مزیتی داره؟ تشکر

سلام.
تابعی رو باید inline کنید که Instruction های مورد استفاده در اون بسیار کم باشه، فرضا تابعی با 10 خط کد رو نباید inline کنید. در حقیقت، inline کردن یک تابع، فقط hint ای برای Compiler هستش، تا Compiler در صورت وجود شرایط، تابع رو inline در نظر بگیره (هیچ ضزوزتی نداره که inline کردن تابعی باعث بشه تا اون تابع واقعا Inline شده باشه). اگر تابع مورد نظر در L1 Cache پردازنده (http://en.wikipedia.org/wiki/CPU_cache)قرار نگیره، اوضاع میتونه کاملا برخلاف انتظار پیش بره و اجرای تابع بطور چشمگیری کند بشه. بسیاری از Compiler های جدید، inline رو بطور کلی نادیده میگیرن و بر اساس خواص heuristics (http://en.wikipedia.org/wiki/Heuristic) مسیر اجرایی کد، تصمیم به inline کردن یا نکردن یک تابع میگیرن. (منظور از خواص Heuristic خواصی است که بر اساس تعداد Call شدن های کد مشخصی، حجم کد، شاخه های اجرایی مختلف کد و ... باعث میشه تا بخش هایی از کد اجرا، یا بخش های دیگری در شرایط ویژه نادیده گرفته بشه). این خواص هستن که به Compiler نشون میدن که آیا Inline کردن تابعی در کل، صحیح هست یا خیر. بنابراین، زیاد روی این مساله تاکید نکنید و اجازه بدید Optimizer کار خودش رو انجام بده. فرضا در روزگاران قدیم، Data Type حلقه ها رو با کلمه کلیدی register مارک می کردیم تا بدین ترتیب Compiler اون متغیر رو در CPU Register قرار بده تا سرعت اجرای حلقه بالا باشه:

for (register int index = 0; index < upperBound; index++) {
}

اما امروزه شرایط تغییر کرده و Compiler ها بخوبی میتونن Code ها رو Optimize کنن و دیگه نیازی به درگیر شدن با Compiler نیست. :)

موفق باشید.

Arashdn
جمعه 24 آذر 1391, 08:48 صبح
شرمنده ، ما یه ذره IQ مون پایینه و متوجه بحث نشدیم ...

الان دقیقا تابع inline چجور تابعی هست و چه فرقی با تابع معمولی داره؟؟؟

mehdi.mousavi
جمعه 24 آذر 1391, 09:02 صبح
شرمنده ، ما یه ذره IQ مون پایینه و متوجه بحث نشدیم ...
الان دقیقا تابع inline چجور تابعی هست و چه فرقی با تابع معمولی داره؟؟؟

سلام.
داستان از این قراره که تابع Inline به Compiler میگه که هنگام کامپایل کردن باید جای فراخوانی تابع Inline،
Body ی اون تابع رو همونجایی که Call اش کرده ایم قرار بده، گویی که از ابتدا ما تابعی رو فراخوانی نکرده ایم.

این تابع رو که از Wikipedia کپی کرده ام، ببینید:

inline int max(int a, int b) {
return (a > b) ? a : b;
}

حالا فرض کنید تابع فوق رو جایی در کد به شکل زیر Call کرده ایم:

a = max(x, y);

Compiler، جای اینکه بیاد این تابع رو Call کنه، میاد محتوای اون خط رو این در نظر میگیره:

a = (x > y) ? x : y;

گویی که اصلا تابع max ای در کار نبوده! (به این کار میگن Inline Expansion).

موفق باشید.

Arashdn
جمعه 24 آذر 1391, 09:19 صبح
سلام.
داستان از این قراره که تابع Inline به Compiler میگه که هنگام کامپایل کردن باید جای فراخوانی تابع Inline،
Body ی اون تابع رو همونجایی که Call اش کرده ایم قرار بده، گویی که از ابتدا ما تابعی رو فراخوانی نکرده ایم.

این تابع رو که از Wikipedia کپی کرده ام، ببینید:

inline int max(int a, int b) {
return (a > b) ? a : b;
}

حالا فرض کنید تابع فوق رو جایی در کد به شکل زیر Call کرده ایم:

a = max(x, y);

Compiler، جای اینکه بیاد این تابع رو Call کنه، میاد محتوای اون خط رو این در نظر میگیره:

a = (x > y) ? x : y;

گویی که اصلا تابع max ای در کار نبوده! (به این کار میگن Inline Expansion).

موفق باشید.
پس تنها کاربردش اینه که برنامه خواناتر میشه و هیچ فرقی با نوشتن کد نداره
درسته؟

mehdi.mousavi
جمعه 24 آذر 1391, 10:22 صبح
پس تنها کاربردش اینه که برنامه خواناتر میشه و هیچ فرقی با نوشتن کد نداره درسته؟

شما باید کاری که انجام میدید رو به اجزاء کوچکتر مدیریت پذیری تقسیم کنید که هر کدوم وظیفه خاص و مشخصی رو انجام بدن. این کار با شکستن کدهای طولانی به توابع متعدد و Call کردن اون توابع امکان پذیره. اما وقتی تابعی رو Call می کنید، واقعا چه اتفاقی داره میفته؟ آیا فراخوانی توابع متعدد، باعث کند شدن برنامه میشه؟ سیستم چطوری باید عمل Context Switching رو انجام بده و ...؟

وقتی شما تابعی رو فراخوانی می کنید، چیزی به اسم Stack Frame تشکیل میشه که محتوای اون عبارت است از:


Formal Parameter های اون تابع (پارامترهایی که تابع در Signature خودش اونها رو داره)
آدرس بازگشتی تابع
Frame Pointer
اگر تابع شما try/catch داره، اطلاعات SEH
متغیرهای تعریف شده محلی
و ...

جمع آوری همه این اطلاعات برای این هستش که پس از اتمام کار تابع، سیستم بتونه عمل Context Switching رو انجام بده و مابقی کد اجرا بشه. حالا وقتی شما تابعی رو inline تعریف می کنید، در حقیقت دارید به Compiler میگید که این کارها رو نکنه و Body ی تابع رو در همون محل فراخوانی قرار بده. طبیعتا چون مراحل فوق حذف میشه، سرعت اجرای کد بالا میره (البته، با توجه به شرایط Heuristic کد که در فوق به اون اشاره کردم).

موفق باشید.

مصطفی ساتکی
جمعه 24 آذر 1391, 14:58 عصر
شما می تونید کامپایلر رو مقید کنید که تصمیم گیری برای inline کردن توابع به صورت اتوماتیک نباشه با رهنمود __forceinline و برعکس declspec(noinline__) البته این 2 مورد رو بایستی زمانی استفاده کنید وقتی کد رو disassemble می کنید بتونید کد بهتری رو جایگزین کنید که در آن مورد خاص تصمیم کامپایلر اشتباه بود البته افرادی که به صورت تخصصی روی performance کار می کنند از این رهنمود ها استفاده می کنند.
البته استفاده از توابع inline یک trade off بین میزان حجم کد و سرعت اجرای توابع هستند و استفاده آن نسبت به ماکرو هم مزیت داره.
در انتها اینکه اگر کدتون کدتون بیش از cache l1 باشه باز هم Inline کردن توابع بی معنا هستش