আমি কীভাবে জি সি সি কে বলতে পারি কোনও ফাংশন ইনলাইন না করা?


126

বলুন আমি একটি উত্স ফাইলে এই ছোট ফাংশন আছে

static void foo() {}

এবং আমি আমার বাইনারিটির একটি অপ্টিমাইজড সংস্করণ তৈরি করি তবুও আমি এই ফাংশনটি ইনলাইন করা চাই না (অনুকূলিতকরণের উদ্দেশ্যে)। ইনলাইনিং প্রতিরোধের জন্য আমি কোনও উত্স কোড যুক্ত করতে পারি এমন কোনও ম্যাক্রো আছে?


এই প্রশ্নের জন্য ধন্যবাদ! যখন আমি কোনও ফাংশন প্রদর্শিত না হত, তখন আমি oprofile দিয়ে প্রোফাইলিং করছিলাম, উত্তরগুলি এখানে এটি স্থির করেছে।
সাইমন এ। ইউগস্টার

উত্তর:


149

আপনি- gccবিশিষ্ট noinlineবৈশিষ্ট্য চান ।

এই ফাংশন বৈশিষ্ট্যটি কোনও ক্রিয়াকে ইনলাইনের জন্য বিবেচনা করা থেকে বাধা দেয় ts যদি ফাংশনটির পার্শ্ব-প্রতিক্রিয়া না থাকে তবে ইনলাইনিং ব্যতীত অপ্টিমাইজেশন রয়েছে যা ফাংশন কলটি লাইভ থাকলেও ফাংশন কলগুলি অপ্টিমাইজড করে তোলে। এই জাতীয় কলগুলি অপ্টিমাইজ করা থেকে দূরে রাখতে, রাখুন asm ("");

এটি এর মতো ব্যবহার করুন:

void __attribute__ ((noinline)) foo() 
{
  ...
}

32
আর্ক লিনাক্সে জিসিসি ৪.৪.৩ ব্যবহার করে উপরের বৈশিষ্ট্যযুক্ত একটি সিনট্যাক্স ত্রুটি পেয়েছি। এটি ঠিকঠাকভাবে কাজ করে যখন এটি ফাংশনটির আগে (যেমন, অ্যাট্রিবিউট ((নোনলাইন)) শূন্য ফু ()}})
এমআরকেজ

2
আরডুইনোও চাইতেন এটি ফাংশনের আগেই রাখা হোক।
পিটার এন লুইস

2
বৈশিষ্ট্য সিনট্যাক্স ঠিক করতে সম্পাদিত।
কুক্সপ্লসোন

1
Asm ("") নির্মাণ আসলে মোটামুটি ক্রস প্ল্যাটফর্ম এবং কাজটি সম্পন্ন করে। আমি এটি x86 লিনাক্সের জন্য করেছি এবং এটি পাওয়ারপিসি এআইএক্স-এ বিল্ড সমস্যা তৈরি করে না। এই দরকারী পরামর্শের জন্য ধন্যবাদ!
মার্টি

1
যে পদ্ধতির কোডগুলির পরিবর্তে সর্বত্র প্রয়োজন সেই যুক্তিটি যথাযথভাবে গ্রহণযোগ্য উত্তর হিসাবে বিবেচনা করা যাবে না।
আজিহ

31

জিসিসির একটি সুইচ কল রয়েছে

-fno-inline-small-functions

জিসিসি চালানোর সময় এটি ব্যবহার করুন that তবে এর পার্শ্ব প্রতিক্রিয়াটি হ'ল অন্যান্য সমস্ত ছোট কার্যগুলিও অন-ইনলাইনড।


সংকলক স্তরে কাজ করেনি। Gcc 5.2.1 20150902 (রেড হ্যাট 5.2.1-2) ব্যবহার করছিল
জন গ্রীন

হয় বর্তমান জিসিসি 6.4 ভাঙা হয়েছে, বা এটি এবং সরল -fno-inlineকিছুতেই কাজ করে না। gdbস্টেপ-ওভারে এখনও পদ্ধতি প্রবেশ করে। কিছু ভেঙে গেছে, এবং আমার সন্দেহ হয় gdb
আজিহ

এটি কেবল নির্দিষ্ট ফাংশনের জন্য নয়, সকলের জন্য ইনলাইন অপ্টিমাইজেশন বন্ধ করে দেবে।
যেখানে 23

@ ইজেহ ইনলাইনিং ফাংশনগুলির অর্থ হ'ল এগুলি সাধারণত বলা হয়, তাই না?
মেলিবিয়াস

21

এটি করার একটি বহনযোগ্য উপায় হ'ল পয়েন্টারের মাধ্যমে ফাংশনটি কল করা:

void (*foo_ptr)() = foo;
foo_ptr();

যদিও এটি শাখাকে বিভিন্ন নির্দেশনা দেয়, যা আপনার লক্ষ্য নাও হতে পারে। কি: যা একটি ভাল বিন্দু দেখাবে হয় আপনার লক্ষ্য এখানে?


2
যদি পয়েন্টারটি ফাইল স্কোপে সংজ্ঞায়িত করা হয় এবং স্থিতিশীল না হয় তবে এটি সংকলক হিসাবে কাজ করা উচিত তবে ব্যবহারের সময় এটির প্রাথমিক মান আছে বলে ধরে নেওয়া যায় না। যদি এটি স্থানীয় হয় (যেমন দেখানো হয়েছে) তবে এটি অবশ্যই ফু () এর মতোই আচরণ করবে। ("এই দশকে", তিনি তারিখগুলির দিকে তাকিয়ে যোগ করেছেন)
গ্রেগগো

16

আমি জানি যে প্রশ্নটি জিসিসি সম্পর্কে, তবে আমি ভেবেছিলাম অন্যান্য সংকলক সংকলকগুলির সম্পর্কেও কিছু তথ্য থাকতে পারে এটি কার্যকর।

noinline অন্যান্য সংকলকগুলির সাথেও জিসিসির ফাংশন বৈশিষ্ট্যটি বেশ জনপ্রিয়। এটি অন্ততপক্ষে সমর্থন করে:

  • ঝাঁকুনি (সাথে পরীক্ষা করা __has_attribute(noinline))
  • ইন্টেল সি / সি ++ সংকলক (তাদের ডকুমেন্টেশন ভয়ানক, তবে আমি নিশ্চিত এটি 16.0+ এ কাজ করে)
  • ওরাকল সোলারিস স্টুডিও কমপক্ষে 12.2 এ ফিরে আসুন
  • এআরএম সি / সি ++ কমপাইলারটি কমপক্ষে 4.1 এ ফিরে যান
  • আইবিএম এক্সএল সি / সি ++ কমপক্ষে 10.1 এ ফিরে আসুন
  • টিআই 8.0+ (বা --gcc সহ 7.3+, যা সংজ্ঞায়িত করবে __TI_GNU_ATTRIBUTE_SUPPORT__)

অতিরিক্তভাবে, এমএসভিসি __declspec(noinline) ভিজ্যুয়াল স্টুডিও 7.1 এ ফিরে সমর্থন করে । ইন্টেল সম্ভবত এটি সমর্থন করে (তারা জিসিসি এবং এমএসভিসি উভয়ের সাথেই সামঞ্জস্যপূর্ণ হওয়ার চেষ্টা করে) তবে আমি এটি যাচাই করতে বিরত হইনি। বাক্য গঠনটি মূলত:

__declspec(noinline)
static void foo(void) { }

PGI 10.2+ (এবং সম্ভবত আরও পুরানো) একটি noinlineপ্রগমা সমর্থন করে যা পরবর্তী ফাংশনে প্রযোজ্য:

#pragma noinline
static void foo(void) { }

টিআই 6.0+ একটি FUNC_CANNOT_INLINE প্রগমা সমর্থন করে যা (বিরক্তিকরভাবে) সি এবং সি ++ এ আলাদাভাবে কাজ করে। সি ++ তে এটি পিজিআইয়ের মতো:

#pragma FUNC_CANNOT_INLINE;
static void foo(void) { }

সি তে তবে ফাংশনটির নামটি প্রয়োজনীয়:

#pragma FUNC_CANNOT_INLINE(foo);
static void foo(void) { }

ক্র 6.৪++ (এবং সম্ভবত পূর্ববর্তী) একই ধরণের পন্থা গ্রহণ করে, ফাংশনটির নাম প্রয়োজন:

#pragma _CRI inline_never foo
static void foo(void) { }

ওরাকল ডেভেলপার স্টুডিও একটি প্রগমা সমর্থন করে যা ফাংশনটির নাম নেয়, কমপক্ষে ফোর্ট ডেভেলপার to- ফিরে যায় তবে নোট করুন যে এটি ঘোষণার পরেও হওয়া দরকার, এমনকি সাম্প্রতিক সংস্করণগুলিতে:

static void foo(void);
#pragma no_inline(foo)

আপনি কতটা উত্সর্গীকৃত তার উপর নির্ভর করে আপনি একটি ম্যাক্রো তৈরি করতে পারেন যা সর্বত্র কাজ করবে তবে আপনার ফাংশনটির নাম এবং তর্ক হিসাবে তদন্তের প্রয়োজন হবে।

যদি ওটিওহ, আপনি এমন কিছু দিয়ে ঠিক আছেন যা বেশিরভাগ মানুষের পক্ষে কাজ করে তবে আপনি এমন কিছু নিয়ে দূরে সরে যেতে পারেন যা কিছুটা নান্দনিকভাবে আনন্দদায়ক এবং নিজেকে পুনরাবৃত্তি করার প্রয়োজন নেই। হেডলির জন্য আমি এটাই গ্রহণ করেছি , যেখানে HEDLEY_NEVER_INLINE এর বর্তমান সংস্করণটি দেখে মনে হচ্ছে:

#if \
  HEDLEY_GNUC_HAS_ATTRIBUTE(noinline,4,0,0) || \
  HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
  HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
  HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
  HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
  HEDLEY_TI_VERSION_CHECK(8,0,0) || \
  (HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
#  define HEDLEY_NEVER_INLINE __attribute__((__noinline__))
#elif HEDLEY_MSVC_VERSION_CHECK(13,10,0)
#  define HEDLEY_NEVER_INLINE __declspec(noinline)
#elif HEDLEY_PGI_VERSION_CHECK(10,2,0)
#  define HEDLEY_NEVER_INLINE _Pragma("noinline")
#elif HEDLEY_TI_VERSION_CHECK(6,0,0)
#  define HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
#else
#  define HEDLEY_NEVER_INLINE HEDLEY_INLINE
#endif

আপনি যদি হিডলি ব্যবহার করতে না চান (এটি একটি একক পাবলিক ডোমেন / সিসি শিরোলেখ) আপনি খুব বেশি প্রচেষ্টা ছাড়াই সংস্করণ চেকিং ম্যাক্রোগুলিকে রূপান্তর করতে পারেন তবে আমি যে পরিমাণটি দিতে চাই তাতে তার চেয়ে বেশি ☺


আপনার প্রকল্প @ লিঙ্কের লিঙ্কের জন্য ধন্যবাদ। আমি আমাদের অন্যান্য বিকাশকারীদের এটি আমাদের ব্যবহারের জন্য মূল্যায়ন করতে বলেছি। আমাদের বিভিন্ন আর্কিটেকচার রয়েছে।
ডাইসুক আরমাকি

তারা কী বলে বিশেষত যদি তারা আগ্রহী না হয় তবে আমি জানতে আগ্রহী হব । এবং অবশ্যই, আমি প্রশ্নের উত্তর দিতে পারি (গিটহাব ইস্যু ট্র্যাকার, ই-মেইল, যাই হোক না কেন ...)।
nemequ

14

যদি আপনি এর জন্য একটি সংকলক ত্রুটি পান তবে __attribute__((noinline))আপনি কেবল চেষ্টা করতে পারেন:

noinline int func(int arg)
{
    ....
}

10
static __attribute__ ((noinline))  void foo()
{

}

এটিই আমার পক্ষে কাজ করেছিল।


8

noinline বৈশিষ্ট্যটি ব্যবহার করুন :

int func(int arg) __attribute__((noinline))
{
}

আপনি যখন বাহ্যিক ব্যবহারের জন্য ফাংশনটি ঘোষণা করেন এবং ফাংশনটি লেখেন তখন আপনার সম্ভবত এটি উভয়ই ব্যবহার করা উচিত।


2

আমি জিসিসি 7.2 নিয়ে কাজ করি। অন-ইনলাইনড হওয়ার জন্য আমার বিশেষত একটি ফাংশন প্রয়োজন, কারণ এটি একটি লাইব্রেরিতে ইনস্ট্যান্ট করতে হয়েছিল। আমি __attribute__((noinline))উত্তরটি পাশাপাশি উত্তরটিও চেষ্টা করেছিলাম asm("")। কেউই সমস্যার সমাধান করেনি।

পরিশেষে, আমি বুঝতে পেরেছি যে ফাংশনের অভ্যন্তরে একটি স্থির পরিবর্তনশীল সংজ্ঞায়িত করা সংস্থাপককে স্থির ভেরিয়েবল ব্লকের জন্য এটির জন্য স্থান বরাদ্দ করতে বাধ্য করবে এবং ফাংশনটি প্রথম যখন ডাকা হবে তখন এটির জন্য একটি সূচনা জারি করতে বাধ্য করবে।

এটি এক ধরণের নোংরা কৌশল, তবে এটি কার্যকর।


আপনি inline void foo(void) { ... }একটি শিরোনামে আপনার ফাংশনটি সংজ্ঞায়িত করতে এবং এটি extern inline void foo(void);একটি লাইব্রেরি উত্স ফাইলটিতে ঘোষণা করতে পারেন । সি 99 শব্দার্থবিজ্ঞানের পরে, সংকলকটি যখন আপনার লাইব্রেরিতে অবজেক্ট কোডটি পছন্দ করে এবং প্রেরণ করবে তখন ফাংশনটিকে ইনলাইন করার অনুমতি দেওয়া হবে। দেখুন কি "স্ট্যাটিক" ছাড়া "ইনলাইন" বা "এক্সটার্নাল" সি 99 এ কখনও কার্যকর?
ডায়াপির
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.