c++ - কেন স্টাডি:: optionচ্ছিক<<< স্ট্যান্ডিং:: জোড়<<, বুল> এর চেয়ে বেশি ব্যয়বহুল নির্মাণ?




performance assembly (3)

get_std_optional_int() জন্য কেন তিনটি get_my_optional() নির্দেশিকা প্রয়োজন, যখন get_my_optional() কেবলমাত্র একটি একক movabs ?

এর প্রত্যক্ষ কারণ হ'ল alচ্ছিকটি কোনও গোপন পয়েন্টারের মাধ্যমে ফেরত দেওয়া হয় এবং pair কোনও রেজিস্টারে ফেরত দেওয়া হয়। কেন, যদিও? এসআইএসভি এবিআই স্পেসিফিকেশন, বিভাগ ৩.২.৩ পরামিতি পাসিং বলেছেন:

যদি কোনও সি ++ অবজেক্টের হয় একটি তুচ্ছ ত্রুটিযুক্ত অনুলিপি নির্মাণকারী বা একটি তুচ্ছ ত্রুটিযুক্ত ডিস্ট্রাক্টর থাকে তবে এটি অদৃশ্য রেফারেন্স দ্বারা পাস করা হয়।

+চ্ছিক সি ++ মেস বাছাই করা সহজ নয়, তবে আমি যাচাই করেছিলাম বাস্তবায়নের al optional_base শ্রেণিতে কমপক্ষে একটি তুচ্ছ-অনুলিপি অনুলিপি নির্মাণকারী বলে মনে হচ্ছে।

এই দুটি পদ্ধতির বিবেচনা করুন যা একটি "al int " উপস্থাপন করতে পারে:

using std_optional_int = std::optional<int>;
using my_optional_int = std::pair<int, bool>;

এই দুটি ফাংশন দেওয়া ...

auto get_std_optional_int() -> std_optional_int 
{
    return {42};
}

auto get_my_optional() -> my_optional_int 
{
    return {42, true};
}

... উভয় জি ++ ট্রাঙ্ক এবং ঝনঝন ++ ট্রাঙ্ক ( -std=c++17 -Ofast -fno-exceptions -fno-rtti ) নিম্নলিখিত সমাবেশ উত্পাদন করে:

get_std_optional_int():
        mov     rax, rdi
        mov     DWORD PTR [rdi], 42
        mov     BYTE PTR [rdi+4], 1
        ret

get_my_optional():
        movabs  rax, 4294967338 // == 0x 0000 0001 0000 002a
        ret

Godbolt.org এ সরাসরি উদাহরণ

get_std_optional_int() জন্য কেন তিনটি get_my_optional() নির্দেশিকা প্রয়োজন, যখন get_my_optional() কেবলমাত্র একটি একক movabs ? এটি কিউইউআই ইস্যু, বা std::optional alচ্ছিকের নির্দিষ্টকরণের মধ্যে এই অপ্টিমাইজেশনটি আটকাচ্ছে কিছু আছে?

এছাড়াও দয়া করে নোট করুন যে ফাংশনগুলির ব্যবহারকারীরা নির্বিশেষে সম্পূর্ণরূপে অনুকূলিত হতে পারে:

volatile int a = 0;
volatile int b = 0;

int main()
{
    a = get_std_optional_int().value();
    b = get_my_optional().first;
}

...ফলাফল স্বরূপ:

main:
        mov     DWORD PTR a[rip], 42
        xor     eax, eax
        mov     DWORD PTR b[rip], 42
        ret

libstdc ++ দৃশ্যত P0602 "বৈকল্পিক প্রয়োগ করে না এবং andচ্ছিকভাবে অনুলিপি / নকল সরানো উচিত" । আপনি এটি দিয়ে যাচাই করতে পারেন:

static_assert(std::is_trivially_copyable_v<std::optional<int>>);

যা libstdc ++ এর জন্য ব্যর্থ হয়, এবং libc ++ এবং MSVC স্ট্যান্ডার্ড লাইব্রেরির জন্য পাস হয় (যার সত্যিকার অর্থে সঠিক নাম প্রয়োজন তাই আমাদের এটিকে "সি ++ স্ট্যান্ডার্ড লাইব্রেরির এমএসভিসি বাস্তবায়ন" বা "দ্য MSVC STL" বলতে হবে না)।

অবশ্যই এমএসভিসি এখনও রেজিস্টারে একটি optional<int> পাস করবে না কারণ এমএস এবিআই।

সম্পাদনা: এই সমস্যাটি জিসিসি 8 রিলিজ সিরিজে স্থির করা হয়েছে।


অপ্টিমাইজেশানটি প্রযুক্তিগতভাবে অনুমোদিত , এমনকি std::is_trivially_copyable_v<std::optional<int>> মিথ্যা std::is_trivially_copyable_v<std::optional<int>> । যাইহোক, এটি সংকলকটি খুঁজে পেতে "চালাকি" এর একটি অযৌক্তিক ডিগ্রির প্রয়োজন হতে পারে। এছাড়াও, কোনও ফাংশনের রিটার্ন টাইপ হিসাবে std::optional ব্যবহারের নির্দিষ্ট ক্ষেত্রে, সংকলন-সময়ের পরিবর্তে লিঙ্ক-টাইমে অপ্টিমাইজেশন করা প্রয়োজন।

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

সংকলক এই অপ্টিমাইজেশনটি সন্ধান করতে পারে তা ধরে নিয়ে, তারপরে এই ফাংশনটির কলিং কনভেনশন (যেমন ফাংশন একটি প্রদত্ত মানকে কীভাবে ফিরিয়ে দেয়) পরিবর্তন করতে হবে, যা সাধারণত লিঙ্ক সময়ে করা দরকার কারণ কলিং কনভেনশন সমস্ত কল সাইটকেই প্রভাবিত করে। বিকল্পভাবে, সংকলক সম্পূর্ণরূপে ফাংশনটি ইনলাইন করতে পারে, যা সংকলন সময়ে করা সম্ভবও হতে পারে। তুচ্ছ-অনুলিপিযোগ্য বস্তুর সাথে এই পদক্ষেপগুলি প্রয়োজনীয় হবে না, সুতরাং এই অর্থে মানটি অপটিমাইজেশনকে বাধা দেয় এবং জটিল করে তোলে।

std::is_trivially_copyable_v<std::optional<int>> হওয়া উচিত সত্য ought যদি এটি সত্য হয় তবে সংযোজকগণের পক্ষে এই অপ্টিমাইজেশানটি আবিষ্কার করা এবং সম্পাদন করা অনেক সহজ হবে। সুতরাং, আপনার প্রশ্নের উত্তর দিতে:

এটি কিউইউআই ইস্যু, বা std::optional alচ্ছিকের নির্দিষ্টকরণের মধ্যে এই অপ্টিমাইজেশনটি আটকাচ্ছে কিছু আছে?

এটা উভয়। অনুমানটি অপ্টিমাইজেশন সন্ধান করা যথেষ্ট শক্ত করে তোলে এবং বাস্তবায়নগুলি "স্মার্ট" পর্যাপ্ত নয় যে এটি সীমাবদ্ধতার অধীনে এটি সন্ধান করতে পারে।

* ধরে নেওয়া যে আপনি সত্যিই অদ্ভুত কিছু করেন নি, যেমন #define int something_else





c++17