শিথিল আদেশ ক্রম ব্যাখ্যা cppreferences মধ্যে ভ্রান্ত?


13

ইন ডকুমেন্টেশন std::memory_ordercppreference.com উপর নিরুদ্বেগ ক্রম একটি উদাহরণ থাকে:

স্বচ্ছন্দ অর্ডার

পারমাণবিক ক্রিয়াকলাপগুলি memory_order_relaxedসিঙ্ক্রোনাইজেশন অপারেশন নয়; তারা সমবর্তী মেমরি অ্যাক্সেসগুলির মধ্যে কোনও অর্ডার চাপায় না। তারা কেবল পারমাণবিকতা এবং পরিবর্তন আদেশের সামঞ্জস্যের গ্যারান্টি দেয়।

উদাহরণস্বরূপ, x এবং y শুরুতে শূন্যের সাহায্যে

// Thread 1:
r1 = y.load(std::memory_order_relaxed); // A
x.store(r1, std::memory_order_relaxed); // B
// Thread 2:
r2 = x.load(std::memory_order_relaxed); // C
y.store(42, std::memory_order_relaxed); // D

r1 == r2 == 42 উত্পাদনের অনুমতি দেওয়া হয়েছে কারণ, যদিও A থ্রেড 1 এর মধ্যে B এর আগে সিকোয়েন্সড হয় এবং থ্রেড 2 এর মধ্যে সি এর অনুক্রম হয় তবে Y এর সংশোধন ক্রমে D এর আগে উপস্থিত হতে কোনও কিছুই D কে বাধা দেয় না এবং B এক্স এর পরিবর্তনের ক্রমে সি এর সামনে উপস্থিত হওয়া। D এ Y এর পার্শ্ব-প্রতিক্রিয়া থ্রেড 1 এ লোড এ-এর কাছে দৃশ্যমান হতে পারে এবং বি তে X এর পার্শ্ব প্রতিক্রিয়া থ্রেড 2-এ লোড সি-তে দৃশ্যমান হতে পারে D বিশেষত, ডি সি এর পূর্বে সম্পন্ন হলে এটি ঘটতে পারে থ্রেড 2, হয় সংকলক পুনর্বিন্যাসের কারণে বা রানটাইম এর কারণে।

এটি বলে যে "থ্রেড 2 এর মধ্যে ডি এর আগে সি অনুক্রমযুক্ত"।

সিক্যুয়েন্সড-পূর্বের সংজ্ঞা অনুসারে, যা অর্ডার অফ মূল্যায়নে পাওয়া যায় , যদি A এর পূর্বে বি সিকোয়েন্সড করা হয়, তবে খ এর মূল্যায়ন শুরুর আগে A এর মূল্যায়ন সম্পন্ন হবে। যেহেতু সি থ্রেড 2 এর মধ্যে ডি এর আগে ক্রমযুক্ত, তাই ডি শুরু হওয়ার আগে সি পূর্ণ করতে হবে, সুতরাং স্ন্যাপশটের শেষ বাক্যটির শর্তের অংশটি কখনই সন্তুষ্ট হবে না।


আপনার প্রশ্নটি কি বিশেষত সি ++ 11 সম্পর্কে?
কৌতূহলী

না, এটি সি ++ 14,17 এর ক্ষেত্রেও প্রযোজ্য। আমি জানি যে সংকলক এবং সিপিইউ উভয়ই ডি এর সাথে সি পুনরায় অর্ডার করতে পারে তবে যদি পুনরায় অর্ডারিং ঘটে তবে ডি শুরু হওয়ার আগে সি পূর্ণ করা যায় না। সুতরাং আমি মনে করি "A থ্রেড 1 এর মধ্যে বি এর আগে সিকোয়েন্সড-সি এবং থ্রেড 2 এর মধ্যে ডি এর আগে সিকোয়েন্সড" বাক্যটিতে একটি পরিভাষা-অপব্যবহার রয়েছে। এটি আরও সঠিকভাবে বলা "কোডটিতে A থ্রেড 1 এর মধ্যে B এর আগে এবং প্লাস্টিকটি থ্রেড 2 এর মধ্যে ডি স্থানের আগে রাখা হয়" more এই প্রশ্নের উদ্দেশ্য এই চিন্তার নিশ্চিত করতে হয়
abigaile

"পুনর্বিন্যাস" শব্দটিতে কিছুই সংজ্ঞায়িত হয় না।
কৌতূহলী

উত্তর:


12

আমি বিশ্বাস করি cppreferences সঠিক। আমি মনে করি এটি "as-if" বিধি [intro.execution] / 1 এ ফোটে । সংকলকরা কেবল আপনার কোড দ্বারা বর্ণিত প্রোগ্রামটির পর্যবেক্ষণযোগ্য আচরণ পুনরুত্পাদন করতে বাধ্য। এই মূল্যায়নগুলি সম্পাদনা করা হয় এমন থ্রেডের দৃষ্টিকোণ থেকে মূল্যায়নের মধ্যে একটি সিকোয়েন্সড- পূর্বের সম্পর্ক স্থাপন করা হয় [অন্তঃসারণ] / 15 । এর অর্থ যখন দুটি মূল্যায়ন একের পরে একের পর এক থ্রেডে উপস্থিত হয়, তখন সেই থ্রেডটিতে চলমান কোডটি অবশ্যই আচরণ করবে যেমন প্রথম মূল্যায়ন যা ঘটেছিল তা সত্যই দ্বিতীয় মূল্যায়ন যা ঘটে তা প্রভাবিত করে। উদাহরণ স্বরূপ

int x = 0;
x = 42;
std::cout << x;

অবশ্যই print২ টি মুদ্রণ করতে হবে However তবে, সংকলকটিকে আসলে xএটি মুদ্রণের জন্য সেই বস্তুটি থেকে মানটি পড়ার আগে 42২ মান কোনও বস্তুতে সংরক্ষণ করতে হবে না। এটি পাশাপাশি মনে রাখতে পারে যে সর্বশেষ মানটি সংরক্ষণ করতে হবে x42 ছিল এবং তারপরে 42 মূল্য থেকে একটি আসল স্টোর করার আগে কেবল 42 মানটি মুদ্রণ করে x। প্রকৃতপক্ষে, যদি xস্থানীয় ভেরিয়েবল হয় তবে এটি কেবলমাত্র সেই মানটি ট্র্যাক করতে পারে যে কোনও স্থানে চলকটি সর্বশেষভাবে নির্ধারিত হয়েছিল এবং কখনও কোনও বস্তু তৈরি করতে বা বাস্তবে মানটি 42 সংরক্ষণ করে না thread থ্রেডটির পার্থক্য বলার উপায় নেই। আচরণ সবসময় হতে যাচ্ছে যেন সেখানে একটি পরিবর্তনশীল ছিল এবং যেন মান 42 আসলে একটি বস্তু মধ্যে সংরক্ষিত হয় x আগেযে বস্তু থেকে বোঝা হচ্ছে। তবে এর অর্থ এই নয় যে উত্পন্ন মেশিন কোডটি আসলে যে কোনও জায়গায় যে কোনও কিছু সংরক্ষণ এবং লোড করতে হয়। যে সমস্ত প্রয়োজন তা হ'ল উত্পাদিত মেশিন কোডের পর্যবেক্ষণযোগ্য আচরণটি যদি এই সমস্ত জিনিস আসলে ঘটে থাকে তবে আচরণটি কী হতে পারে তা থেকে পৃথক।

আমরা যদি তাকান

r2 = x.load(std::memory_order_relaxed); // C
y.store(42, std::memory_order_relaxed); // D

তবে হ্যাঁ, ডি এর আগে সি ধারাবাহিকভাবে তৈরি করা হয়েছে, কিন্তু যখন এই থ্রেডটি বিচ্ছিন্নভাবে দেখা যায়, সি কিছু করে না তা ডি এর ফলাফলকে প্রভাবিত করে এবং D যা কিছু করে তা সি এর ফলাফলকে পরিবর্তন করতে পারে না কারণ একমাত্র অন্যটিকে প্রভাবিত করতে পারে একমাত্র উপায় would অন্য থ্রেডে ঘটে যাওয়ার কিছু পরোক্ষ পরিণতি হিসাবে। তবে, নির্দিষ্ট করে std::memory_order_relaxedআপনি স্পষ্ট করে বলেছেনযে লোড এবং স্টোরটি অন্য থ্রেড দ্বারা পর্যবেক্ষণ করা হয় তা অপ্রাসঙ্গিক। যেহেতু অন্য কোনও থ্রেড কোনও নির্দিষ্ট ক্রমে লোড এবং স্টোরটি পর্যবেক্ষণ করতে পারে না, সি এবং ডি একে অপরকে নিয়মিতভাবে প্রভাবিত করার জন্য আর কোনও থ্রেড করতে পারে না। সুতরাং, লোড এবং স্টোরটি আসলে যে ক্রমে সম্পাদিত হয় তা অপ্রাসঙ্গিক। সুতরাং, সংকলক তাদের পুনঃক্রম করতে বিনামূল্যে। এবং, যেমন উদাহরণের নীচে ব্যাখ্যায় উল্লিখিত হিসাবে, ডি থেকে স্টোরটি যদি সি থেকে লোডের আগে সঞ্চালিত হয়, তবে r1 == r2 == 42 আসলেই আসতে পারে ...


সুতরাং মূলত স্ট্যান্ডার্ডটি উল্লেখ করে যে ডি এর আগে সি অবশ্যই ঘটেছিল , তবে সংকলক বিশ্বাস করেন যে সি বা ডি এর পরের ঘটনা ঘটেছে কিনা তা প্রমাণিত হতে পারে না এবং বিধি-বিধানের কারণে এগুলি যেভাবেই হোক না কেন, সঠিক?
ফিউরিয়েশ

4
@ ফিউরিশ নং সি অবশ্যই তাদের থ্রেডটি যে থ্রেডটি বলতে পারে তার পূর্ব পর্যন্ত ডি এর আগে অবশ্যই ঘটবে। অন্য প্রসঙ্গ থেকে পর্যবেক্ষণ করা সেই দৃষ্টিতে অসঙ্গতিপূর্ণ হতে পারে।
Deduplicator

কোনও "যেমন নিয়ম" নেই
কৌতূহলী

4
@ কুরিয়াসগুয়ে এই দাবিটি আপনার অন্যান্য, পূর্ববর্তী, সি ++ ধর্ম প্রচারের সাথে সমান বলে মনে হচ্ছে ।
অরবিটে

1
@curiousguy মান আছে এটা বিধান "হিসেবে-যদি রুল" একটি পাদটীকা মধ্যে লেবেল এক: "এই বিধান কখনও কখনও বলা হয়" হিসাবে-যদি "বিধি" অর্থ intro.execution
Caleth

1

একে অপরের সাথে সম্পর্কিত sequ ক্রমগুলিতে ক্রিয়াকলাপের কোনও আপেক্ষিক ক্রমকে বোঝানো না করে ক্রিয়াকলাপের সাথে অন্য দুটি ক্রমগুলির তুলনায় ক্রম অর্ডার করা সম্ভব হয়।

ধরুন, উদাহরণস্বরূপ, একটিতে নিম্নলিখিত তিনটি ইভেন্ট রয়েছে:

  • 1 থেকে p1 সঞ্চয় করুন
  • টেম্পে পি 2 লোড করুন
  • 2 থেকে p3 সঞ্চয় করুন

এবং পি 2 পড়ার পি 1 লেখার পরে এবং পি 3 লেখার আগে স্বাধীনভাবে অর্ডার করা হয় তবে পি 1 এবং পি 3 উভয়ই অংশ নেয় এমন কোনও নির্দিষ্ট ক্রম নেই। পি 2 দিয়ে যা করা হয়েছে তার উপর নির্ভর করে কোনও সংকলক পি 1 অতীত পি 3 মুলতুবি করা এবং এখনও পি 2 দিয়ে প্রয়োজনীয় শব্দার্থবিজ্ঞান অর্জন করা অবৈধ হতে পারে। মনে করুন, তবে সংকলকটি জানত যে উপরের কোডটি একটি বৃহত্তর অনুক্রমের অংশ ছিল:

  • 1 থেকে পি 2 সঞ্চয় করুন [পি 2 এর লোডের আগে ক্রম]
  • [উপরের কাজ]
  • 3 টি পি 1-তে সংরক্ষণ করুন

সেক্ষেত্রে এটি নির্ধারণ করতে পারে যে উপরের কোডের পরে এটি স্টোরটিকে পি 1 এ পুনরায় অর্ডার করতে পারে এবং নীচের স্টোরের সাথে এটি একত্রীকরণ করতে পারে, ফলস্বরূপ কোডটি যা প্রথমে পি 1 না লিখে p3 লিখে:

  • অস্থায়ী সেট 1
  • টেম্প টু পি 2
  • 2 থেকে p3 সঞ্চয় করুন
  • 3 থেকে p1 সঞ্চয় করুন

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


1

যদি দুটি বিবৃতি থাকে তবে সংকলকটি ক্রমানুসারে কোড তৈরি করবে তাই প্রথমটির কোড দ্বিতীয়টির আগে স্থাপন করা হবে। তবে সিপাসের অভ্যন্তরীণভাবে পাইপলাইন রয়েছে এবং সমান্তরালে সমাবেশ পরিচালনা করতে সক্ষম হয়। বিবৃতি সি একটি বোঝার নির্দেশ। স্মৃতি আনার সময় পাইপলাইনটি পরবর্তী কয়েকটি নির্দেশাবলী প্রক্রিয়া করবে এবং প্রদত্ত তারা লোড নির্দেশনার উপর নির্ভরশীল নয় যা তারা সি শেষ হওয়ার আগেই শেষ করা যেতে পারে (যেমন ডি এর ডেটা ক্যাশে ছিল, মূল স্মৃতিতে সি ছিল)।

যদি ব্যবহারকারীর সত্যতই দুটি বিবৃতি ক্রমান্বয়ে কার্যকর করতে হয় তবে কঠোর মেমরির ক্রম ক্রিয়াকলাপ ব্যবহার করা যেতে পারে। প্রোগ্রামটি লজিক্যালি সঠিক হিসাবে সাধারণ ব্যবহারকারীরা ততক্ষণ যত্ন নিচ্ছেন না।


-7

আপনি যা ভাবেন তা সমানভাবে বৈধ। মানটি ক্রমানুসারে কী সম্পাদন করে, কী করে না এবং কীভাবে এটি মিশ্রিত করা যায় তা বলে না

একাধিক পিএইচডি করার যোগ্য একটি কাজ, এই জগাখিচুড়ি শীর্ষে একটি ধারাবাহিক শব্দার্থবিজ্ঞান তৈরি করা আপনার এবং প্রতিটি একক প্রোগ্রামারের পক্ষে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.