সি ++ কম্পাইলাররা এই শর্তযুক্ত বুলিয়ান অ্যাসাইনমেন্টটিকে শর্তহীন অ্যাসাইনমেন্ট হিসাবে অনুকূল করে না কেন?


117

নিম্নলিখিত ফাংশন বিবেচনা করুন:

void func(bool& flag)
{
    if(!flag) flag=true;
}

আমার কাছে মনে হয় যে পতাকাটির বৈধ বুলেটিন মান থাকলে এটি এটি শর্তহীন নির্ধারণের সমতুল্য হবে true:

void func(bool& flag)
{
    flag=true;
}

তবুও জিসিসি বা ঝনঝন উভয়ই এটিকে অপ্টিমাইজ করে না - উভয়ই -O3অপ্টিমাইজেশন স্তরে নিম্নলিখিতটি উত্পন্ন করে :

_Z4funcRb:
.LFB0:
    .cfi_startproc
    cmp BYTE PTR [rdi], 0
    jne .L1
    mov BYTE PTR [rdi], 1
.L1:
    rep ret

আমার প্রশ্ন হচ্ছে: এটা ঠিক যে কোড খুব বিশেষ-ক্ষেত্রে দেখা যায় নিখুত গ্রাহ্য, অথবা কোন ভাল কারণে যেমন অপ্টিমাইজেশান অবাঞ্ছিত করা হবে হয় করা হয়, প্রদত্ত যে flagএকটি রেফারেন্স নয় volatile? এটি কেবল কারণ বলে মনে হতে পারে যে এটি পড়ার সময় flagকোনওভাবেই trueঅপরিজ্ঞাত falseআচরণ ছাড়াই অ - মান - মূল্য থাকতে পারে তবে এটি সম্ভব কিনা তা আমি নিশ্চিত নই।


8
এটি একটি "অনুকূলিতকরণ" যে কোনও প্রমাণ আছে কি?
ডেভিড শোয়ার্টজ

1
@ 200_সাক্সেস আমি মনে করি না যে শিরোনাম হিসাবে অ-কার্যকারী মার্কআপের সাথে কোডের একটি লাইন স্থাপন একটি ভাল জিনিস। আপনি একটি আরো নির্দিষ্ট শিরোনাম, জরিমানা চান কিন্তু একটি চয়ন ইংরেজী বাক্য (যেমন, এবং এটি কোড এড়ানোর চেষ্টা যখন তারা বিশ্বাসীদেরকে প্রমাণ করতে পারেন সমতুল্য? হতে কেন কম্পাইলার নিঃশর্ত লিখেছেন করতে শর্তাধীন লিখেছেন অপটিমাইজ করেন না বা অনুরূপ)। এছাড়াও যেহেতু ব্যাকটিকগুলি রেন্ডার করা হয় না আপনি কোড ব্যবহার করলেও তাদের শিরোনামে ব্যবহার করবেন না।
বাকুরিউ

2
@ রুস্লান, যদিও এটি নিজেরাই এই ফাংশনটির জন্য এই অপ্টিমাইজেশনটি করার কথা বলে মনে হচ্ছে না, যখন এটি কোডটি ইনলাইন করতে পারে, অন্তর্নিহিত সংস্করণটির জন্য এমনটি মনে হয় না। প্রায়শই 1ব্যবহারের নিয়মিত সময় সংকলনের ফলে ঘটে । Godbolt.org/g/swe0tc
ইভান

উত্তর:


102

ক্যাশে সমন্বয় বিবেচনার কারণে এটি প্রোগ্রামের কার্যকারিতাটিকে নেতিবাচকভাবে প্রভাবিত করতে পারে । flagপ্রতিটি সময় লেখার জন্য func()বলা ক্যাশে লাইন নোংরা হবে। এটি লিখিত হওয়ার আগে গন্তব্য ঠিকানায় পাওয়া বিটগুলির সাথে ঠিক লিখিতভাবে মানের সাথে মিল রেখেই ঘটবে।


সম্পাদনা

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

আরও কিছুটা প্রতিবিম্বের পরে আমি আরও একটি উদাহরণ প্রস্তাব করতে পারি যে সংকলকগণকে কেন কঠোরভাবে নিষিদ্ধ করা উচিত - যদি না তারা প্রমাণ করতে পারে যে রূপান্তরটি কোনও নির্দিষ্ট প্রসঙ্গে নিরাপদ - নিঃশর্ত রচনার প্রবর্তন থেকে। এই কোডটি বিবেচনা করুন:

const bool foo = true;

int main()
{
    func(const_cast<bool&>(foo));
}

এতে নিঃশর্ত লিখিতভাবে func()অবশ্যই অনির্ধারিত আচরণকে ট্রিগার করে (কেবল পঠনযোগ্য মেমরির জন্য লেখা প্রোগ্রামটি শেষ করে দেবে, এমনকি লেখার প্রভাবটি যদি কোনও অনিচ্ছুক হয়)।


7
আপনি কোনও শাখা থেকে মুক্তি পাওয়ার পরে এটি কার্য সম্পাদনে ইতিবাচক প্রভাব ফেলতে পারে। সুতরাং আমি মনে করি না যে এই নির্দিষ্ট কেসটি খুব সুনির্দিষ্ট ব্যবস্থাটি মাথায় না রেখে আলোচনা করা অর্থবহ।
লন্ডিন

3
@ ইয়াক্ক আচরণের সংজ্ঞাটি লক্ষ্য প্ল্যাটফর্ম দ্বারা প্রভাবিত হয় না। এটি প্রোগ্রামটি শেষ করে দেবে তা বলাই ভুল, তবে ইউজ নিজেই অনুনাসিক দানব সহ সুদূরপ্রসারী পরিণতি ঘটাতে পারে।
জন ডিভোরাক

16
@ ইয়াক্ক এটি "পঠনযোগ্য কেবল স্মৃতি" বলতে কী বোঝায় তার উপর নির্ভর করে। না, এটি কোনও রম চিপে নেই, তবে এটি এমন পৃষ্ঠায় লোড হওয়া একটি অংশে প্রায়শই থাকে যা লেখার অ্যাক্সেস সক্ষম করে না এবং আপনি যেমন লেখার চেষ্টা করার সময় একটি সিগসাইজিভি সিগন্যাল বা STATUS_ACCESS_VIOLATION ব্যতিক্রম পাবেন।
র্যান্ডম 832

5
"এটি অবশ্যই অনির্ধারিত আচরণকে ট্রিগার করে"। না। সংজ্ঞায়িত আচরণ বিমূর্ত মেশিনের সম্পত্তি is কোডটি যা ইউবি উপস্থিত রয়েছে কিনা তা নির্ধারণ করে বলে is সংকলকরা এটি তৈরি করতে পারে না (যদিও বাগী সংকলক প্রোগ্রামগুলি ভুলভাবে আচরণ করতে পারে)।
এরিক এম শমিট

7
constকোনও ফাংশনে প্রবেশ করা দূরে থাকাই শর্তহীন লিখন নয়, অপরিজ্ঞাত আচরণের উত্স, এমন ডেটা সংশোধন করতে পারে । ডক্টর, আমি যখন এটি করি তখন ব্যথা হয় ....
স্প্যান্সার

48

পারফরম্যান্সে লিওনের উত্তর বাদে:

ধরুন flagহয় true। ধরুন দুটি থ্রেড ক্রমাগত কল করছে func(flag)। লিখিত হিসাবে ফাংশন, সেক্ষেত্রে, কিছুই সংরক্ষণ করে না flag, তাই এটি থ্রেড-নিরাপদ হওয়া উচিত। দুটি থ্রেড একই স্মৃতিতে অ্যাক্সেস করে তবে কেবল এটি পড়তে পারে। নিঃশর্তভাবে সেট flagকরার trueঅর্থ দুটি পৃথক থ্রেড একই মেমরিতে লেখা থাকবে। এটি নিরাপদ নয়, লিখিত তথ্যটি ইতিমধ্যে উপস্থিত তথ্যের অনুরূপ থাকলেও এটি অনিরাপদ।


9
আমি মনে করি এটি প্রয়োগের ফলাফল [intro.races]/21
গ্রিভস

10
খুব আকর্ষণীয়. সুতরাং আমি এটি এই হিসাবে পড়লাম: সংকলকটি কখনও লিখন ক্রিয়াকলাপে "অনুকূলিতকরণ" করার অনুমতি দেয় না যেখানে বিমূর্ত মেশিনটি না থাকে।
মার্টিন বা

3
@ মার্টিনবা বেশিরভাগ ক্ষেত্রেই। তবে যদি সংকলকটি প্রমাণ করতে পারে যে এটি কোনও বিষয় নয়, উদাহরণস্বরূপ কারণ এটি প্রমাণ করতে পারে যে অন্য কোনও থ্রেডের সম্ভবত সেই নির্দিষ্ট ভেরিয়েবলের অ্যাক্সেস থাকতে পারে না, তবে এটি ঠিক আছে।

13
এটি কেবল অনিরাপদ যদি কম্পিউটারটি সংকলকটি লক্ষ্য করে এটি নিরাপদ করে তোলে । আমি এমন কোনও সিস্টেমে বিকাশ পাইনি যেখানে 0x01ইতিমধ্যে 0x01"অনিরাপদ" আচরণের কারণ বাইটে লেখা । শব্দ বা ডওয়ার্ড মেমরি অ্যাক্সেস সহ এমন একটি সিস্টেমে এটি হবে; তবে অপ্টিমাইজারটি এ সম্পর্কে সচেতন হওয়া উচিত। একটি আধুনিক পিসি বা ফোন ওএসে, কোনও সমস্যা দেখা দেয় না। সুতরাং এটি কোনও বৈধ কারণ নয়।
ইয়াক্ক - অ্যাডাম নেভ্রামামন্ট

4
@ ইয়াক্ক আসলে আরও বেশি চিন্তাভাবনা করে আমার মনে হয় এটি সাধারণভাবে প্রসেসরের ক্ষেত্রেও ঠিক আছে। আমি মনে করি আপনি যখন সিপিইউ সরাসরি মেমোরিতে লিখতে পারেন ঠিক তখনি, তবে মনে করুন flagকোনও অনুলিপি-অন-পৃষ্ঠায় রয়েছে। এখন, সিপিইউ স্তরে, আচরণটি সংজ্ঞায়িত করা যেতে পারে (পৃষ্ঠা ত্রুটি, ওএস এটি পরিচালনা করতে পারে) তবে ওএস স্তরে এটি এখনও অপরিজ্ঞাত হতে পারে, তাই না?

13

আমি এখানে সি ++ এর আচরণ সম্পর্কে নিশ্চিত নই, তবে সি-তে মেমরির পরিবর্তন হতে পারে কারণ মেমরিটিতে যদি 1 ব্যতীত শূন্য-এর মান থাকে, তবে এটি চেকের সাথে অপরিবর্তিত থাকবে, তবে চেক সহ 1 এ পরিবর্তিত হবে।

তবে আমি যেহেতু সি ++ তে খুব সাবলীল নই, আমি জানি না যে এই পরিস্থিতি এমনকি সম্ভব কিনা।


এটি কি এখনও সত্য হবে _Bool?
Ruslan

5
সি-তে, যদি মেমরিটিতে এমন কোনও মান থাকে যা এবিআই না বলে তার ধরণের জন্য এটি বৈধ, তবে এটি একটি ফাঁদ উপস্থাপনা, এবং একটি ফাঁদ উপস্থাপনা পড়া অবধারিত আচরণ। সি ++ এ, এটি কেবল তখনই ঘটতে পারে যখন একটি অনির্দেশিত বস্তুটি পড়ে এবং এটি ইউবি-র একটি অবিচ্ছিন্ন অবজেক্টটি পড়ে। তবে আপনি যদি এমন একটি এবিআই খুঁজে পেতে পারেন যা বলে যে কোনও শূন্য-মান মান টাইপ bool/ _Boolএবং অর্থের জন্য বৈধ true, তবে সেই নির্দিষ্ট এবিআইতে, আপনি সম্ভবত সঠিক right

1
@ রুসালান সংকলকগুলি যা ইটানিয়াম এবিআই ব্যবহার করে এবং এআরএম প্রসেসরের উপর, সি _Boolএবং সি ++ boolহয় একই ধরণের, বা সামঞ্জস্যপূর্ণ ধরণের যা একই নিয়ম অনুসরণ করে। এমএসভিসির সাথে তাদের আকার এবং প্রান্তিককরণ একই রয়েছে তবে তারা একই বিধিগুলি ব্যবহার করে কিনা সে সম্পর্কে কোনও আনুষ্ঠানিক বিবৃতি নেই।
জাস্টিন সময় - মনিকা

1
@ জাস্টিনটাইম: সি এর <stdbool.h>মধ্যে একটি typedef _Bool bool; এবং হ্যাঁ রয়েছে, x86 এ (কমপক্ষে সিস্টেম ভি এবিআইতে), bool/ _Boolবাইটের উপরের বিটগুলি সাফ করে 0 বা 1 হওয়া দরকার। এই ব্যাখ্যাটি প্রশংসনীয় বলে আমি মনে করি না।
পিটার কর্ডেস

1
@ জাস্টিনটাইম: এটি সত্য, আমার কেবল এটি উল্লেখ করা উচিত ছিল যে সিস্টেম ভি এবিআইয়ের সমস্ত x86 স্বাদে এটির স্পষ্টতই শব্দার্থকতা রয়েছে, যা এই প্রশ্নটি সম্পর্কে ছিল। (আমি বলতে পারি কারণ প্রথম আরগটি আরডিআইতে funcপাস হয়েছিল, যখন উইন্ডোজ আরডিএক্স ব্যবহার করবে)।
পিটার কর্ডেস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.