انجمنهای فارسی اوبونتو
کمک و پشتیبانی => راهنماها، نکات و ترفندها => نویسنده: fond در 29 اردیبهشت 1392، 07:23 بظ
-
سلام
فقط میخوام یه توضیحات مختصری درباره کامپایلر بدم و اینکه چطور میشه برنامه ها رو با انجام یه سری بهینهسازی هایی کامپایل کرد.
در حالت معمولی، برای کامپایل یک برنامه c یا ++c، کافیه اون رو توی یه ویرایشگر بنویسید و با پسوند c یا cxx یا cpp (برای ++c) ذخیره کنید. بعد با این دستور برنامه رو کامپایل کنید:
cc -o program.out source.c
که source.c کد منبع برنامه هست و program.o فایل اجرایی برنامه. اما کامپایلر تعداد زیادی آپشن داره که با استفاده از اونها میشه کد بهینه تری تولید کرد.
-march
این آپشن نوع پردازنده رو تعیین میکنه. طبیعی هست که کامپایلر اگه نوع پردازنده رو بدونه میتونه object code بهینه تری برای اون پردازنده و با استفاده از دستورالعملهای اون تولید کنه.
-O
این گزینه سطح optimization یا همون بهینه سازی رو مشخص میکنه. این آپشن یه عدد به عنوان آرگومان میگیره که اون عدد سطح بهینه سازی رو مشخص میکنه. سطح 0 بدون انجام بهینه سازی هست. سطح صفر سریعترین زمان کامپایل رو داره و کدی که تولید میشه رو راحتتر میشه دیباگ کرد. اما به هر حال توی سرعت برنامه تاثیر نداره. سطح 2 بهترین حالت بهینه سازی هست و توی این حالت کامپایلر معمولا بهینه سازی های زیادی انجام میده و کد بسیار عالی میکنه. سطح s شبیه همون 2 هست اما کامپایلر سعی میکنه حجم فایل خروجی رو هم کمتر کنه. سطح z هم مانند s و 2 هست اما باز هم با حجم پایینتر. یادتون باشه هر چی حجم فایل اجرایی پایینتر باشه، دیباگ کردن اون هم سخت تر میشه. اما خطرناکترین سطح سطح 3 هست که کامپایلر سعی میکنه همه توابع رو بصورت inline کامپایل کنه و حجم برنامه بشدت زیاد میشه و فقط وقتی استفاده کنید که میدونید دارید چیکار میکنید. سطح پیشنهادی من 2 هست. مثلا:
cc -O2 source.c
-pipe
برای کامپایل شدن یه برنامه، کدمنبع باید از چند مرحله عبور کنه: پیشپردازنده، کامپایل و لینک. خروجی هر مرحله توی یه سری فایل معمولی توی دیسک ذخیره میشه به این صورت به مرحله بعدی ارسال میشه. با آپشن pipe- میشه به کامپایلر پیشنهاد کرد که خروجی هر مرحله رو از طریق pipe ها به مرحله بعد بفرسته که مسلما این کار سریعتر از ذخیره کردن توی دیسک هست اما خب ram زیادی احتیاج داره.
-g
این گزینه باعث میشه کامپایلر کدی تولید کنه که دیباگ کردن اون بسیار راحت باشه. این گزینه حجم فایل رو بشدت افزایش میده. هیچ برنامهای رو نباید با این گزینه کامپایل کنید مگر اینکه برنامه نویس هستید و میخواهید برنامه رو خطایابی کنید
-Wall
با این گزینه میتونید همه warning ها رو ببینید.
-Werror
این گزینه همه warning ها رو به error تبدیل میکنه و میتونید با رفع اونها کد بهینه تری تولید کنید.
-D
میتونید یه ماکرو تعریف کنید. مثلا DWITH_X11- برابر است با:
#define WITH_X11
-l
با این گزینه میتونید برنامه رو به یک کتابخانه لینک کنید. مثلا اگه توی برنامه از توابع ریاضی استفاده کرده باشید، باید کدمنبع رو به کتابخانه libm.a لینک کنید. با فرض اینکه اسم کتابخانه libsomething.a هست، باید با lsomething- کد رو لینک کنید.
-fPIC
همه shared library ها رو باید با این آپشن کامپایل کنید. این گزینه کمک میکنه تا کتابخانه از هر آدرس دلخواهی لود بشه.
خب با همه این توضیحات، میتونید موقع کامپایل برنامه متغیر CFLAGS رو مقدار دهی کنید تا برنام ها بصورت بهینه کامپایل بشن:
CFLAGS= -O2 -pipe -march=core2
-
۱+
-
خیلی مفید بود ++
میشه در رابطه با پسوند های مختلف سورس هم کمی توضیح بدید؟
-
بسیار ممنونم.
میشه لطفا درباره march بیشتر توضیح بدید؟
-
در مورد march، همونطور که گفتم نوع پردازنده رو به کامپایلر اعلام میکنه و کامپایلر با دونستن نوع پردازنده، میدونه که باید از چه دستورات زبان ماشینی استفاده کنه و خب این سرعت رو بالا میبره. اول شما باید نوع پردازنده خودتون رو تشخیص بدید، اگر درست یادم مونده باشه، توی لینوکس با این دستور میتونید نوع پردازنده رو ببینید:
cat /proc/cpuinfo
بعد از اینکه نوع پردازنده رو فهمیدید، میتونید از مقادیر زیر برای معرفی اون استفاده کنید.
i386
پردازنده i386 اصلی اینتل
i586, pentium
پردازنده معمولی پنتیوم اینتل که از دستورالعمل MMX پشتیبانی نمیکنند.
pentium-mmx
پردازنده پنتیومی که از دستورالعمل MMX پشتیبانی میکنه.
pentiumpro
پردازنده پنیتوم پرو
i686
مثل pentiumpro هست اما کدی که با این معماری کامپایل میشه، روی همه پردازنده های هم خوانواده هم اجرا میشه.
core2
[پردازنده رایج]پردازنده ۶۴ بیتی Core2 که از دستورالعملهای MMX, SSE, SSE2, SSE3 و SSSE3 پشتیبانی میکنه. [/پردازنده رایج]
k8, opteron, athlon64, athlon-fx
پردازنده های AMD K8 شست و چهار بیتی (این پردازنده از همه دستورالعملهای ۶۴ بیت به غیر از SSE3 پشتیبانی میکنند.)
k8-sse3, opteron-sse3, athlon64-sse3
مثل بالایی هست اما برای پردازنده هایی که دستورالعمل SSE3 هم پشتیبانی میکنند.
از دوستان اگر کسی توی شناسایی پردازنده مشکل داره مشخصات پردازندش رو اعلام کنه تا اگه تونستیم راهنمایی کنیم. برای اکثر پردازنده های اینتل چند هسته ای رایج توی لپتاپها مثل core i5 و corei3 و core i7 همون مقدار core2 درست هست.
MHA میشه بیشتر توضیح بدی؟ منظورتون رو خوب نفهمیدم. خب برنامههایی که به زبان c نوشتید رو با پسوند .c ذخیره کنید و برنامههای ++c رو هم با پسوند .cxx یا .cpp
دو نکته خیلی مهم:
اگر march- رو روی native تنظیم کنید کامپایلر سعی میکنه خودش نوع پردازنده رو حدس بزنه که امتحانش البته ضرری نداره اما بهتره شما خودتون نوع پردازتون رو بدونید.
اگر نوع اشتباه استفاده کنید، به احتمال زیاد برنامه ها درست کار نخواهند کرد!!
-
سورس چه با cpp ذخیره بشه چه cxx هیچ فرقی نمی کنه؟این دو نوع مدل برای چی ساخته شدند؟
-
استفاده از march=core2 یعنی این برنامه رو برای CPU های ۶۴ بیتی کامپایل کن. درسته؟
پس یعنی من میتونم یه برنامه رو بنویسم و با این آپشن اون رو برای ۶۴ بیتی کامپایل کنم. با اینکه سیستم عاملم ۳۲ بیت هست. آره؟
-
سورس چه با cpp ذخیره بشه چه cxx هیچ فرقی نمی کنه؟این دو نوع مدل برای چی ساخته شدند؟
فرقی که نمیکنه و هر دو یکی هست. اما به غیر از اینها چیز دیگه ای سعی کن نباشه. چون کامپایلر میتونه از طریق پسوند زبان برنامه رو تشخیص بده. من معمولا .cxx میذارم اما خب کاملا سلیقه ای هست.
استفاده از march=core2 یعنی این برنامه رو برای CPU های ۶۴ بیتی کامپایل کن. درسته؟
پس یعنی من میتونم یه برنامه رو بنویسم و با این آپشن اون رو برای ۶۴ بیتی کامپایل کنم. با اینکه سیستم عاملم ۳۲ بیت هست. آره؟
تا اونجایی که من میدونم، بله میشه. به این میگن cross compile. اما بسته به برنامه شاید تغییرات دیگه هم لازم باشه.
-
آیا این فلگها مخصوص زبان سی هستن یا برای زبانهای دیگه هم به همین شکله؟
کلا بنظ بد نباشه که یه قسمتی داخل ویکی برای این فلگها ایجاد بشه و دوستانی که آشنایی دارن کاملترش کنن. ???
-
خیلییییییی بدرد خورد ممنون :)