মাল্টি থ্রেডিংয়ের সাথে অস্থিরতা কখন ব্যবহার করবেন?


130

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

সুতরাং একাধিক-থ্রেড প্রোগ্রামে অস্থির ব্যবহার / উদ্দেশ্য কী?


3
কিছু ক্ষেত্রে, আপনি মুটেক্স দ্বারা সুরক্ষার প্রয়োজন / চান না।
স্টেফান মাই

4
কখনও কখনও এটি একটি দৌড় অবস্থা আছে জরিমানা, কখনও কখনও এটি না। আপনি এই পরিবর্তনশীলটি কীভাবে ব্যবহার করছেন?
ডেভিড হেফারনান

3
@ ডেভিড: দৌড় প্রতিযোগিতা করা কখন "ভাল" এর উদাহরণ, দয়া করে?
জন ডিবলিং

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

5
@ জন এই হার্ডওয়্যারটিতে এই কোডটি চালিত করে তা গ্যারান্টি দেয় যে প্রান্তিককরণযুক্ত ভেরিয়েবলগুলি ছেঁড়াতে পারে না। যদি পাঠক পাঠক হিসাবে কর্মী n + 1 কে আপডেট করে থাকেন তবে পাঠকরা n বা n + 1 পান কিনা সে বিষয়ে তার কোন চিন্তা নেই। এটি কেবল অগ্রগতি প্রতিবেদনের জন্য ব্যবহৃত হওয়ায় কোনও গুরুত্বপূর্ণ সিদ্ধান্ত নেওয়া হবে না।
ডেভিড হেফারনান

উত্তর:


167

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

অন্যদিকে, এর volatileকিছু ব্যবহার রয়েছে যা এতো সুস্পষ্ট নাও হতে পারে। এটি constসংকলকটি আপনাকে দেখাতে সহায়তা করতে একইভাবে ব্যবহার করা যেতে পারে যেখানে আপনি কোনও অ-সুরক্ষিত উপায়ে কিছু ভাগ করা সংস্থান অ্যাক্সেস করতে ভুল করতেই পারেন। এই ব্যবহারটি এই নিবন্ধে আলেকজান্দ্রেস্কু দ্বারা আলোচনা করা হয়েছে । তবে এটি মূলত সি ++ টাইপ সিস্টেমটি এমনভাবে ব্যবহার করছে যা প্রায়শই একটি স্বতন্ত্রতা হিসাবে দেখা হয় এবং অনির্ধারিত আচরণকে উত্সাহিত করতে পারে।

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

2003-এর সি ++ স্ট্যান্ডার্ডটি বলছে না যে volatileভেরিয়েবলগুলিতে কোনও ধরণের অর্জিত বা প্রকাশিত শব্দার্থক প্রয়োগ করে। আসলে, স্ট্যান্ডার্ডটি মাল্টিথ্রেডিংয়ের সমস্ত বিষয়ে সম্পূর্ণ নীরব। তবে নির্দিষ্ট প্ল্যাটফর্মগুলি volatileভেরিয়েবলগুলিতে অ্যাকুইয়ার এবং রিলিজ শব্দার্থ প্রয়োগ করে apply

[সি ++ 11 এর জন্য আপডেট]

সি ++ 11 স্ট্যান্ডার্ড এখন সরাসরি মেমরি মডেল এবং ল্যাঙ্গোয়েজে মাল্টিথ্রেডিং স্বীকৃতি দেয় এবং এটি প্ল্যাটফর্ম-স্বতন্ত্র পদ্ধতিতে এটি মোকাবেলার জন্য গ্রন্থাগারের সুবিধা সরবরাহ করে। তবে এর শব্দার্থবিজ্ঞানের volatileপরিবর্তন এখনও হয়নি। volatileএখনও একটি সিঙ্ক্রোনাইজেশন প্রক্রিয়া নয়। টিউসিপিপিএল 4 ই তে বাজর্ন স্ট্রস্ট্রপ যতটা বলেছেন:

volatileনিম্ন-স্তরের কোড ব্যতীত ব্যবহার করবেন না যা সরাসরি হার্ডওয়্যার সাথে ডিল করে।

ধরে নিবেন না volatileমেমরির মডেলটির বিশেষ অর্থ রয়েছে। এটা না. এটি কোনও - পরবর্তী ভাষাগুলির মতো নয় - একটি সিঙ্ক্রোনাইজেশন প্রক্রিয়া। সিঙ্ক্রোনাইজেশন পেতে atomic, এ mutex, বা এ ব্যবহার করুন condition_variable

[/ শেষ আপডেট]

উপরের সমস্তটি 2003 এর স্ট্যান্ডার্ড (এবং এখন ২০১১ স্ট্যান্ডার্ড) দ্বারা সংজ্ঞায়িত হিসাবে C ++ ভাষা নিজেই প্রয়োগ করে। কিছু নির্দিষ্ট প্ল্যাটফর্মগুলি তবে যা করে তাতে অতিরিক্ত কার্যকারিতা বা বিধিনিষেধ যোগ volatileকরে। উদাহরণস্বরূপ, MSVC 2010 সালে (অন্তত) অর্জন করতে পারে এবং রিলিজ শব্দার্থবিদ্যা না নির্দিষ্ট অপারেশন উপর প্রয়োগ volatileভেরিয়েবল। এমএসডিএন থেকে :

অপ্টিমাইজ করার সময়, সংকলকটিকে অবশ্যই অস্থায়ী বস্তুর উল্লেখের সাথে সাথে অন্যান্য বিশ্বব্যাপী অবজেক্টের রেফারেন্সগুলির মধ্যে অর্ডার বজায় রাখতে হবে। নির্দিষ্টভাবে,

একটি অস্থির অবজেক্টের একটি লেখায় (উদ্বায়ী রাইটিং) রিলিজ শব্দার্থবিজ্ঞান রয়েছে; সংশ্লেষিত বাইনারিটিতে অস্থির লেখার আগে নির্দেশ ক্রমটিতে একটি অস্থির অবজেক্টে লেখার আগে ঘটে এমন একটি গ্লোবাল বা স্ট্যাটিক অবজেক্টের একটি রেফারেন্স দেখা দেয়।

একটি অস্থির অবজেক্টের পড়ার (অস্থির পড়া) অ্যাকায়ায়ার শব্দার্থবিজ্ঞান রয়েছে; নির্দেশের ক্রমটিতে অস্থির মেমরি পড়ার পরে ঘটে যাওয়া একটি গ্লোবাল বা স্ট্যাটিক অবজেক্টের একটি রেফারেন্স সংকলিত বাইনারিটিতে সেই অস্থির পড়ার পরে ঘটবে।

তবে, আপনি এই বিষয়টি লক্ষ করতে পারেন যে আপনি যদি উপরের লিঙ্কটি অনুসরণ করেন তবে এই ক্ষেত্রে প্রয়োগ / প্রকাশের শব্দার্থকগুলি আসলে প্রয়োগ হয় কিনা সে সম্পর্কে মন্তব্যগুলিতে কিছু বিতর্ক রয়েছে ।


19
আমার অংশটি উত্তরটির সংক্ষিপ্ত সুর এবং প্রথম মন্তব্যের কারণে এটিকে কমিয়ে দিতে চায়। "ম্যানুয়াল মেমোরি বরাদ্দ নিষ্ক্রিয়" এর অনুরূপ "অস্থিরতা অকেজো" আপনি যদি কোনও মাল্টিথ্রেডেড প্রোগ্রাম না লিখে লিখতে পারেন তবে আপনি থ্রেডিং লাইব্রেরি প্রয়োগ করেন volatileএমন লোকদের কাঁধে দাঁড়িয়েছিলেন volatile
বেন জ্যাকসন

19
@ জেন কেবল কারণ কোনও কিছু আপনার বিশ্বাসকে চ্যালেঞ্জ জানায় তা এটিকে ঘৃণ্য করে তোলে না
ডেভিড হেফারনান

38
@Ben: কোন, কী পড়তে volatileআসলে আছে C ++। @ জন যা বলেছেন তা সঠিক , গল্পের শেষ। অ্যাপ্লিকেশন কোড বনাম লাইব্রেরি কোড, বা "সাধারণ" বনাম "godশ্বরের মতো সর্বজ্ঞ প্রোগ্রামারস" এর সাথে এর কোনও সম্পর্ক নেই। volatileথ্রেডগুলির মধ্যে সিঙ্ক্রোনাইজেশনের জন্য অপ্রয়োজনীয় এবং অকেজো। থ্রেডিং গ্রন্থাগারগুলি পদগুলিতে প্রয়োগ করা যায় না volatile; এটিকে যাইহোক প্ল্যাটফর্ম-নির্দিষ্ট বিশদের উপর নির্ভর করতে হবে এবং আপনি যখন সেগুলির উপর নির্ভর করেন তখন আপনার আর প্রয়োজন হয় না volatile
jalf

6
@ জাল্ফ: "থ্রেডগুলির মধ্যে সুসংহতকরণের জন্য উদ্বায়ী অপ্রয়োজনীয় এবং অকেজো" (এটি যা আপনি বলেছিলেন) "মাল্টিথ্রেডেড প্রোগ্রামিংয়ের জন্য উদ্বায়ী বেহুদা" (যা জন উত্তরে বলেছিলেন) এটি একই নয়। আপনি ১০০% সঠিক, তবে আমি জনের সাথে একমত নই (আংশিকভাবে) - অস্থির এখনও মাল্টিথ্রেডেড প্রোগ্রামিংয়ের জন্য ব্যবহার করা যেতে পারে (খুব সীমিত কাজের জন্য)

4
@ জিএমান: দরকারী যে সমস্ত কিছু প্রয়োজনীয়তা বা শর্তগুলির একটি নির্দিষ্ট সেটের অধীনে কেবল কার্যকর। স্থিতিশীলগুলি কড়া অবস্থার (এবং কিছু ক্ষেত্রে বিকল্পের চেয়ে আরও ভাল (কিছু সংজ্ঞা দেওয়ার জন্য)) আরও ভাল হতে পারে এমন একাধিক শর্তে মাল্টিথ্রেডেড প্রোগ্রামিংয়ের জন্য দরকারী। আপনি "এটিকে এবং এটিকে উপেক্ষা" বলছেন তবে যখন অস্থিরতা মাল্টিথ্রেডিংয়ের জন্য কার্যকর তখন কোনও কিছুই উপেক্ষা করে না। আপনি এমন কিছু তৈরি করেছিলেন যা আমি কখনও দাবি করি নি। হ্যাঁ, অস্থিরতার উপযোগিতা সীমিত তবে এটি বিদ্যমান - তবে আমরা সকলেই একমত হতে পারি যে এটি সিঙ্ক্রোনাইজেশনের জন্য কার্যকর নয়।

31

(সম্পাদকের দ্রষ্টব্য: সি ++ 11 volatileএ এই কাজের জন্য সঠিক সরঞ্জাম নয় এবং এখনও ডেটা-রেস ইউবি রয়েছে U ইউবি ছাড়াই এটি করতে লোড / স্টোর std::atomic<bool>সহ ব্যবহার করুন std::memory_order_relaxedreal বাস্তব বাস্তবায়নের ক্ষেত্রে এটি একই asm তে সংকলন করবে volatileI আমি যুক্ত করেছি একটি উত্তর আরো বিস্তারিত সঙ্গে, এবং এছাড়াও মন্তব্য স্বাস্থ্যহীন-বরাত মেমরির এই ব্যবহার-ক্ষেত্রে জন্য একটি সমস্যা হতে পারে ভ্রান্ত ধারনা অ্যাড্রেসিং: সব বাস্তব জগতের সিপিইউ সুসঙ্গত ভাগ মেমরির তাই volatileকাজ করবে এই জন্য বাস্তব সি ++ বাস্তবায়নের উপর কিন্তু এখনও ডন। এটা করবেন না

মন্তব্যে কিছু আলোচনা অন্য ব্যবহারের ক্ষেত্রে কথা বলছে বলে মনে হচ্ছে যেখানে আপনার স্বাচ্ছন্দিত পরমাণুর চেয়ে আরও শক্তিশালী কিছু দরকার হবে । এই উত্তরটি ইতিমধ্যে নির্দেশ করে যা volatileআপনাকে কোনও আদেশ দেয় না))


অস্থিরতা নিম্নলিখিত কারণে মাঝে মাঝে দরকারী: এই কোড:

/* global */ bool flag = false;

while (!flag) {}

জিসিসি দ্বারা এতে অনুকূলিত হয়েছে:

if (!flag) { while (true) {} }

যা অন্য থ্রেড দ্বারা পতাকা লিখিত হলে স্পষ্টতই ভুল। নোট করুন যে এই অপটিমাইজেশন ব্যতীত সিঙ্ক্রোনাইজেশন প্রক্রিয়া সম্ভবত কাজ করে (অন্য কোডের উপর নির্ভর করে কিছু মেমোরি বাধা প্রয়োজন হতে পারে) - 1 নির্মাতায় 1 টি মিউেক্সের প্রয়োজন নেই - 1 ভোক্তির দৃশ্যে।

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


4
যদি আমি মনে করি, সি ++ 0 এক্স পারমাণবিক, বোঝা যাচ্ছে যে অনেক লোক বিশ্বাস করে (ভুলভাবে) উদ্বায়ী হয়।
ডেভিড হেফারনান

13
volatileমেমরি অ্যাক্সেসগুলিকে পুনঃক্রম হতে বাধা দেয় না। volatileঅ্যাক্সেসগুলি একে অপরের প্রতি শ্রদ্ধার সাথে পুনরায় সাজানো হবে না, তবে তারা অ- বস্তুর সাথে সম্মিলিতভাবে পুনরায় অর্ডার করার কোনও গ্যারান্টি সরবরাহ করে না volatileএবং তাই এগুলি পতাকা হিসাবে মূলত অকেজো।
jalf

13
@ বেন: আমার মনে হয় আপনি এটি উল্টো করে পেয়েছেন। "অস্থিরতা অকেজো" ভিড় সরল সত্যের উপর নির্ভর করে যে অস্থিরতা পুনঃক্রমের বিরুদ্ধে সুরক্ষা দেয় না , যার অর্থ এটি সিঙ্ক্রোনাইজেশনের জন্য একেবারেই অকেজো। অন্যান্য পন্থাগুলি সমানভাবে অকেজো হতে পারে (যেমন আপনি উল্লেখ করেছেন, লিঙ্ক-টাইম কোড অপ্টিমাইজেশন সংকলকটিকে কোডটিতে উঁকি দিতে পারে আপনি ধারনা করেছিলেন যে সংকলকটি একটি কালো বক্স হিসাবে বিবেচিত হবে), তবে এর ঘাটতিগুলি ঠিক করে না volatile
জাল্ফ

15
@ জাল্ফ: আর্চ রবিনসনের নিবন্ধটি দেখুন (এই পৃষ্ঠায় অন্যত্র সংযুক্ত), 10 তম মন্তব্য ("স্পড" দ্বারা)। মূলত, পুনঃক্রমটি কোডের যুক্তি পরিবর্তন করে না। পোস্ট কোডটি কোনও কাজ বাতিল করার জন্য পতাকাটি ব্যবহার করে (কার্য সম্পাদন করার চেয়ে সিগন্যাল করার চেয়ে), সুতরাং কোডটির আগে বা পরে কাজটি বাতিল করা হয়েছে while (work_left) { do_piece_of_work(); if (cancel) break;}কিনা তা বিবেচ্য নয় (যেমন: যদি লুপের মধ্যে বাতিলটি পুনরায় সাজানো হয়, যুক্তিটি এখনও বৈধ I আমার কাছে কোডের একটি অংশ ছিল যা একইভাবে কাজ করেছিল: মূল থ্রেডটি যদি শেষ করতে চায় তবে এটি অন্যান্য থ্রেডের জন্য পতাকা নির্ধারণ করে, তবে তা হয় না ...

15
... অন্য থ্রেডগুলি সমাপ্ত হওয়ার আগে তাদের কাজের লুপগুলির অতিরিক্ত কয়েকটি পুনরাবৃত্তি করে, যতক্ষণ তা পতাকা স্থাপনের পরে যুক্তিসঙ্গতভাবে ঘটবে matter অবশ্যই, এটি কেবলমাত্র আমি ব্যবহার করতে পারি যা আমি ভাবতে পারি এবং এর পরিবর্তে কুলুঙ্গি (এবং প্ল্যাটফর্মগুলিতে কাজ করতে পারে না যেখানে অস্থির ভেরিয়েবলে লেখার ফলে অন্যান্য থ্রেডগুলিতে পরিবর্তন দৃশ্যমান হয় না, যদিও কমপক্ষে x86 এবং x86-64 এ কাজ করে)। আমি অবশ্যই কাউকে খুব ভাল কারণ ব্যতীত এটি করার পরামর্শ দেব না, আমি কেবল বলছি যে "মাল্টিথ্রেডেড কোডে কখনও অস্থির নয়" এর মতো একটি কম্বল স্টেটমেন্ট 100% সঠিক নয়।

15

সি ++ 11 এ সাধারণত volatileথ্রেডিংয়ের জন্য কখনও ব্যবহার করবেন না , কেবল এমএমআইওর জন্য

তবে টিএল: ডিআর, এটি mo_relaxedসুসংগত ক্যাশে (অর্থাত্ সবকিছু) সহ হার্ডওয়ারের সাথে পরমাণুর মতো ধরণের "কাজ" করে; এটি রেজিস্টারগুলিতে ভার সংযোজনকারীদের থামাতে যথেষ্ট। atomicপারমাণবিকতা বা আন্ত-থ্রেড দৃশ্যমানতা তৈরি করতে মেমরির বাধাগুলির প্রয়োজন হয় না, কেবল এই থ্রেডের অ্যাক্সেসের মধ্যে বিভিন্ন ভেরিয়েবলের মধ্যে ক্রম তৈরি করার জন্য কোনও ক্রিয়াকলাপের আগে / পরে বর্তমান থ্রেডটিকে অপেক্ষা করতে হবে। mo_relaxedকখনই কোনও বাধা দরকার নেই, কেবল লোড, স্টোর বা আরএমডাব্লু।

সি ++ 11 এর আগের খারাপ পুরানো দিনগুলিতেvolatile (এবং বাধাগুলির জন্য ইনলাইন- এসএম) রোল-আপনার নিজস্ব অ্যাটমিক্সের জন্য , কিছু কাজ করার একমাত্র ভাল উপায় ছিল । তবে বাস্তবায়নগুলি কীভাবে কার্যকর হয়েছিল এবং কোনও মানদণ্ড দ্বারা কখনই গ্যারান্টিযুক্ত ছিল না সে সম্পর্কে অনেক অনুমানের উপর নির্ভর করে।std::atomicvolatile

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

এটি প্রায়শই নতুন প্রকল্পগুলির জন্য ভুল পছন্দ; আপনার std::atomicসাথে std::memory_order_relaxedএকই দক্ষ মেশিন কোড নির্গত করতে একটি সংকলক পেতে আপনি (সহ ) ব্যবহার করতে পারেন volatileথ্রেডিং উদ্দেশ্যে অপ্রচলিত std::atomicসঙ্গে । mo_relaxedvolatile(বাদে কিছু সংকলক সহ মিস-অপ্টিমাইজেশন বাগগুলি নিয়ে কাজ করাatomic<double> বাদে ))

std::atomicমূলধারার সংকলকগুলিতে অভ্যন্তরীণ বাস্তবায়ন (যেমন সিসিসি এবং ঝনঝন) কেবল অভ্যন্তরীণভাবে ব্যবহার করে নাvolatile ; সংকলকগণ সরাসরি পারমাণবিক লোড, স্টোর এবং আরএমডব্লিউ অন্তর্নির্মিত কার্যাদি প্রকাশ করে। (যেমন GNU C __atomicবিল্টিনগুলি যা "প্লেইন" অবজেক্টগুলিতে কাজ করে))


চঞ্চল অনুশীলনে ব্যবহারযোগ্য (তবে এটি করবেন না)

এটি বলেছে যে, সিপিইউ কীভাবে কাজ করে (সুসংগত ক্যাশে) এবং কীভাবে কাজ করা উচিত সে সম্পর্কে ভাগাভাগি করা অনুমানের কারণে, আসল সিপিইউগুলিতে সমস্ত (?) বিদ্যমান সি ++ বাস্তবায়নের উপর পতাকা লাগার volatileমতো জিনিসের জন্য অনুশীলনযোগ্য ব্যবহারযোগ্য exit_now? volatileতবে অন্য কিছু নয় এবং প্রস্তাবিত নয়এই উত্তরের উদ্দেশ্যটি বিদ্যমান সিপিইউ এবং সি ++ বাস্তবায়ন কীভাবে কাজ করে তা ব্যাখ্যা করা। আপনি যদি std::atomicসেটির বিষয়ে চিন্তা করেন না তবে আপনাকে কেবল volatileথ্রেডিংয়ের জন্য মো_ রিল্যাক্সড অপ্রচলিতগুলির সাথে জানা দরকার ।

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


অন্য একটি উত্তরের হিসাবে উল্লেখ করা হয়েছে, একটি exit_nowপতাকা আন্তঃ-থ্রেড যোগাযোগের একটি সহজ কেস যার কোনও সমন্বয় প্রয়োজন হয় না : এটি প্রকাশ করছে না যে অ্যারের সামগ্রীগুলি প্রস্তুত রয়েছে বা এর মতো কিছু or কেবলমাত্র একটি স্টোর যা তাত্ক্ষণিকভাবে অন্য থ্রেডে অপ্টিমাইটিসড-লোড লোড দ্বারা তাত্ক্ষণিকভাবে লক্ষ্য করা গেছে।

    // global
    bool exit_now = false;

    // in one thread
    while (!exit_now) { do_stuff; }

    // in another thread, or signal handler in this thread
    exit_now = true;

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

 // Optimizing compilers transform the loop into asm like this
    if (!exit_now) {        // check once before entering loop
        while(1) do_stuff;  // infinite loop
    }

মাল্টিথ্রেডিং প্রোগ্রামটি অনুকূলিত মোডে আটকে গেছে তবে সাধারণত -O0 এ চলে যায় এর একটি উদাহরণ (জিসিসির এসএম আউটপুট বিবরণ সহ) কীভাবে এটি এক্সএম --6464- তে জিসিসির সাথে ঘটেছিল। এছাড়াও এমসিইউ প্রোগ্রামিং - সি ++ ও 2 অপটিমাইজেশন ব্রেক হয়ে যায় যখন ইলেক্ট্রনিক্সে লুপ হয় SEএসই অন্য একটি উদাহরণ দেখায়।

আমরা সাধারণত আক্রমনাত্মক অপ্টিমাইজেশন চাই যা সিএসই এবং উত্তোলন বৈশ্বিক ভেরিয়েবলগুলি সহ লুপের বাইরে চাপিয়ে দেয়।

সি ++ 11 এর আগে,volatile bool exit_now এই কাজটি উদ্দেশ্য হিসাবে তৈরি করার এক উপায় ছিল (সাধারণ সি ++ বাস্তবায়নে)। তবে সি ++ ১১-এ, ডেটা-রেস ইউবি এখনও প্রযোজ্য volatileতাই এটি এইচএসডাব্লু সংহত ক্যাশে এমনকি ধরে নিলেও বাস্তবে সর্বত্র কাজ করার জন্য আইএসও স্ট্যান্ডার্ড দ্বারা গ্যারান্টিযুক্ত নয় ।

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

নোট করুন যে "উদ্দেশ্য হিসাবে" থ্রেডের অর্থ exit_nowঅন্য থ্রেডটি প্রকৃতপক্ষে প্রস্থান হওয়ার জন্য অপেক্ষা করছে its বা এমনকি এটি যে exit_now=trueএই থ্রেডে পরবর্তী ক্রিয়াকলাপ চালিয়ে যাওয়ার আগে অস্থির স্টোরটি বিশ্বব্যাপী দৃশ্যমান হওয়ার জন্যও অপেক্ষা করে । ( atomic<bool>ডিফল্টরূপে mo_seq_cstএটি পরবর্তী কোনও seq_cst লোড হওয়ার আগে অপেক্ষা করতে সক্ষম করে তোলে many অনেক আইএসএতে আপনি কেবল স্টোরের পরে একটি সম্পূর্ণ বাধা পেতে পারেন)।

সি ++ 11 একটি নন-ইউবি উপায় সরবরাহ করে যা একই সংকলন করে

A অথবা "প্রস্থান এখন" ফ্ল্যাগ ব্যবহার করা উচিত "চলমান রাখতে" std::atomic<bool> flagসঙ্গেmo_relaxed

ব্যবহার

  • flag.store(true, std::memory_order_relaxed)
  • while( !flag.load(std::memory_order_relaxed) ) { ... }

আপনি ঠিক একই asm (কোনও ব্যয়বহুল বাধা নির্দেশাবলী সহ) দেবেন যা আপনি পেয়েছিলেন volatile flag

নন-টিয়ারিংয়ের atomicপাশাপাশি আপনাকে একটি থ্রেডে সঞ্চয় এবং ইউবি ছাড়াই অন্যটিতে লোড করার ক্ষমতাও দেয়, তাই সংকলকটি লুপের বাইরে লোড উত্তোলন করতে পারে না। (কোনও ডেটা রেস ইউবি-র ধারণা হ'ল নন-পারমাণবিক অ-উদ্বায়ী বস্তুগুলির জন্য আমরা যে আগ্রাসী অপ্টিমাইজেশন চাই তা অনুমোদন দেয়)) এই বৈশিষ্ট্যটি খাঁটি লোড এবং খাঁটি স্টোরগুলিতে atomic<T>যা করতে volatileপারে তেমনই একই ।

atomic<T>এছাড়াও করা +=এবং তাই পারমাণবিক RMW অপারেশন মধ্যে (ক অস্থায়ী চালনা, তারপর একটি পৃথক পারমাণবিক দোকান মধ্যে একটি পারমাণবিক লোড তুলনায় উল্লেখযোগ্যভাবে আরো ব্যয়বহুল। আপনি একটি পারমাণবিক RMW না চান তাহলে, একটি স্থানীয় অস্থায়ী সঙ্গে আপনার কোড লিখতে) উপর।

আপনি যে ডিফল্ট seq_cstঅর্ডারটি পেয়েছিলেন while(!flag)তা দিয়ে , এটি ক্রমশ গ্যারান্টি সরবরাহ করে। অ-পারমাণবিক অ্যাক্সেসগুলি এবং অন্যান্য পারমাণবিক অ্যাক্সেসগুলিতে।

(ধারণায়, ISO C ++ স্ট্যান্ডার্ডের atomics এর দ্বারা কম্পাইল-টাইম অপ্টিমাইজেশান বাতিল না। কিন্তু বাস্তবে কম্পাইলার না নিয়ন্ত্রণ করার কোনো উপায় যখন যে ঠিক হবে না কারণ নেই। কিছু ক্ষেত্রে আছে যেখানে এমনকি volatile atomic<T>না করি পারমাণবিকগুলির অপ্টিমাইজেশনের উপর পর্যাপ্ত নিয়ন্ত্রণ থাকুন যদি সংকলকরা অপ্টিমাইজ করে, তবে এখনকারীর জন্য সংকলকরা তা করেন না See দেখুন কম্পাইলারগুলি রিলান্ড্যান্ট এসটিডি সংহত করে না কেন :: পরমাণু লেখেন? নোট করুন যে ডাব্লুজি 21 / পি 10062 volatile atomicঅপ্টিমাইজেশনের বিরুদ্ধে রক্ষা করার জন্য বর্তমান কোড ব্যবহার করার বিরুদ্ধে সুপারিশ করে? atomics।)


volatile প্রকৃত সিপিইউতে এটির জন্য আসলে কাজ করে (তবে এখনও এটি ব্যবহার করবেন না)

এমনকি দুর্বল-অর্ডারযুক্ত মেমরি মডেলগুলির সাথে (নন-x86) । কিন্তু আসলে এটি ব্যবহার করবেন না, ব্যবহার atomic<T>সঙ্গে mo_relaxedপরিবর্তে !! এই বিভাগের বিষয়টি হ'ল আসল সিপিইউগুলি কীভাবে ন্যায়সঙ্গত কাজ করে না তা সম্পর্কে ভুল ধারণাগুলি সমাধান করা volatile। আপনি যদি লকলেস কোড লিখছেন তবে আপনি সম্ভবত কর্মক্ষমতা সম্পর্কে যত্নশীল। ক্যাশে এবং আন্তঃ-থ্রেড যোগাযোগের ব্যয় বোঝা ভাল পারফরম্যান্সের জন্য সাধারণত গুরুত্বপূর্ণ।

রিয়েল সিপিইউগুলিতে সুসংগত ক্যাশে / ভাগ করা মেমরি থাকে: একটি কোর থেকে কোনও স্টোর বিশ্বব্যাপী দৃশ্যমান হওয়ার পরে, অন্য কোনও কোর কোনও বাসি মান লোড করতে পারে না । ( পুরাণ প্রোগ্রামাররাও দেখুন সিপিইউ ক্যাশে সম্পর্কে বিশ্বাস করুন যা জাভা atomic<T>ভোলিটাইলস সম্পর্কে কিছু কথা বলেছে, যা সেক_সিএসটি মেমরি ক্রমের সাথে সি ++ এর সমতুল্য ))

আমি যখন লোড বলি , তখন আমার অর্থ এমন একটি asm নির্দেশ যা স্মৃতিতে অ্যাক্সেস করে। এটিই volatileঅ্যাক্সেস নিশ্চিত করে এবং অ-পরমাণু / অ-উদ্বায়ী সি ++ ভেরিয়েবলের লভ্যালু-টু-রালভ রূপান্তর হিসাবে একই জিনিস নয় । (যেমন local_tmp = flagবা while(!flag))।

আপনাকে কেবলমাত্র পরাজিত করতে হবে কম্পাইল-টাইম অপ্টিমাইজেশন যা প্রথম চেকের পরে পুনরায় লোড হয় না। কোনও ক্রম ছাড়াই প্রতিটি পুনরাবৃত্তিতে যে কোনও লোড + চেক যথেষ্ট। এই থ্রেড এবং মূল থ্রেডের মধ্যে সুসংগততা ব্যতীত কখন স্টোরটি ঘটেছিল বা লোডের আর্টের অর্ডার দেওয়ার কথা বলা অর্থপূর্ণ নয়। লুপ অন্যান্য অপারেশন। কেবলমাত্র যখন এই থ্রেডটিতে দৃশ্যমান হয় তখন তা গুরুত্বপূর্ণ। আপনি প্রস্থান করুন_ পতাকা পতাকাটি দেখলে আপনি প্রস্থান করবেন। টিপিক্যাল x86 সিওনের আন্ত-কোর ল্যাটেন্সি পৃথক শারীরিক কোরের মধ্যে 40ns এর মতো কিছু হতে পারে


তত্ত্বে: সুসংগত ক্যাশেবিহীন হার্ডওয়্যারে সি ++ থ্রেড

সোর্স কোডে স্পষ্টত ফ্লাশ করার জন্য প্রোগ্রামারের প্রয়োজন ছাড়াই কেবল খাঁটি আইএসও সি ++ সহ এটি দূরবর্তীভাবে কার্যকর হতে পারে এমন কোনও উপায়ে আমি দেখছি না।

তত্ত্ব অনুসারে আপনি এমন কোনও মেশিনে সি ++ বাস্তবায়ন করতে পারেন যা এটির মতো ছিল না, সংকলক দ্বারা উত্পাদিত সুস্পষ্ট ফ্লাশগুলি অন্য কোরে অন্য থ্রেডগুলিতে দৃশ্যমান করার জন্য প্রয়োজন । (বা পড়ার জন্য সম্ভবত বাসি অনুলিপি ব্যবহার না করার জন্য)। সি ++ স্ট্যান্ডার্ড এটিকে অসম্ভব করে তোলে না, তবে সি ++ এর মেমরির মডেল সুসংগত শেয়ারড মেমরি মেশিনে দক্ষ হওয়ার আশেপাশে তৈরি করা হয়েছে। যেমন সি ++ স্ট্যান্ডার্ড এমনকি "পঠন-পঠন সমন্বয়", "রাইট-রিড সুসংহততা" ইত্যাদি সম্পর্কে কথা বলে etc. স্ট্যান্ডার্ডের একটি নোট এমনকি হার্ডওয়্যারটির সংযোগকেও নির্দেশ করে:

http://eel.is/c++draft/intro.races#19

[দ্রষ্টব্য: চারটি পূর্ববর্তী সুসংগত প্রয়োজনীয়তা কার্যকরভাবে একক বস্তুতে পারমাণবিক ক্রিয়াকলাপের সংকলক পুনর্বিন্যাসের অনুমতি দেয় না, এমনকি উভয় ক্রিয়াকলাপ শিথিল বোঝা হলেও। এটি কার্যকরভাবে সি ++ পারমাণবিক ক্রিয়াকলাপগুলিতে বেশিরভাগ হার্ডওয়্যার দ্বারা সরবরাহ করা ক্যাশে সংহত গ্যারান্টি তৈরি করে। - শেষ নোট]

কোনও releaseস্টোরের কেবল নিজেই ফ্লাশ করার জন্য এবং কয়েকটি নির্বাচিত অ্যাড্রেস রেঞ্জগুলির কোনও ব্যবস্থা নেই : এটি সমস্ত কিছু সিঙ্ক করতে হবে কারণ যদি তাদের अधिগ্রহন-লোড এই রিলিজ-স্টোরটি দেখে তবে অন্য থ্রেডগুলি কী পড়তে পারে তা এটি জানেন না a রিলিজ-সিকোয়েন্স যা থ্রেড জুড়ে একটি ঘটনার আগে সম্পর্ক স্থাপন করে, গ্যারান্টি দিয়ে যে লেখার থ্রেড দ্বারা করা অ-পারমাণবিক ক্রিয়াকলাপগুলি এখন পড়া নিরাপদ। যদি না রিলিজ স্টোরের পরে তাদের আরও লেখা না থাকে ...) বা সংকলকরা হতে সত্যিই যে মাত্র কয়েক ক্যাশে লাইন প্রয়োজন অনিদ্রা প্রমাণ করার স্মার্ট।

সম্পর্কিত: আমার উত্তর কি মুভি + এমফেন্স NUMA- এ নিরাপদ? সুসংগত ভাগযুক্ত মেমরি ছাড়াই x86 সিস্টেমের অস্তিত্ব সম্পর্কে বিশদে চলে যায়। এছাড়াও সম্পর্কিত: একই স্থানে লোড / স্টোর সম্পর্কে আরও জানতে এআরএম-এ পুনরায় অর্ডারিং লোড এবং স্টোর

সেখানে হয় আমি অ সুসঙ্গত ভাগ করা মেমোরি সঙ্গে ক্লাস্টার মনে করি, কিন্তু তারা একক সিস্টেম-ইমেজ মেশিন নই। প্রতিটি সমন্বিত ডোমেন পৃথক কার্নেল চালায়, সুতরাং আপনি এটির জুড়ে একটি সি সি ++ প্রোগ্রামের থ্রেড চালাতে পারবেন না। পরিবর্তে আপনি প্রোগ্রামটির পৃথক দৃষ্টান্ত চালান (প্রতিটি নিজস্ব ঠিকানা স্পেস সহ: প্রতিটি ক্ষেত্রে পয়েন্টার অন্য ক্ষেত্রে বৈধ নয়)।

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


প্রকৃত হার্ডওয়্যার std::threadক্যাশে সুসংহত সীমানা জুড়ে চলে না :

কিছু সামঁজস্যহীন এআরএম চিপ ভাগ শারীরিক অ্যাড্রেস স্পেস কিন্তু অস্তিত্ব, না ভেতরের-ভাগ করে নেওয়ার যোগ্য ক্যাশে ডোমেনগুলি। সুতরাং সুসংগত না। (যেমন মন্তব্য থ্রেড একটি A8 কোর এবং কর্টেক্স-M3 TI তৈরি সিতারা AM335x মতো)।

তবে পৃথক কার্নেলগুলি সেই কোরগুলিতে চালিত হবে, এমন কোনও একক সিস্টেমের চিত্র নয় যা উভয় কোর জুড়ে থ্রেড চালাতে পারে। আমি কোনও সি ++ বাস্তবায়ন সম্পর্কে সচেতন নই যা std::threadসুসংগত ক্যাশে ছাড়াই সিপিইউ কোর জুড়ে থ্রেড চালায়।

বিশেষত এআরএমের জন্য, সমস্ত থ্রেড একই অভ্যন্তরীণ-ভাগযোগ্য ডোমেনে চালিত হয় তা ধরে নিয়ে জিসি এবং ঝনঝন কোড উত্পন্ন করে। আসলে, এআরএমভি 7 আইএসএ ম্যানুয়ালটি বলেছে

এই আর্কিটেকচার (এআরএমভি 7) এমন এক প্রত্যাশা নিয়ে লেখা হয়েছে যে একই অপারেটিং সিস্টেম বা হাইপারভাইজার ব্যবহারকারী সমস্ত প্রসেসর একই ইনার শেয়ারেবল শেয়ারেবিলিটি ডোমেইনে থাকে

সুতরাং পৃথক ডোমেনগুলির মধ্যে অবিচ্ছিন্ন অংশীদারি মেমরি কেবল আলাদা কার্নেলের অধীনে বিভিন্ন প্রক্রিয়াগুলির মধ্যে যোগাযোগের জন্য ভাগ করে নেওয়া মেমরি অঞ্চলগুলির স্পষ্ট সিস্টেম-নির্দিষ্ট ব্যবহারের জন্য একটি জিনিস।

কোডার -জেন ব্যবহার করে dmb ish(অভ্যন্তরীণ ভাগযোগ্য বাধা) বনাম dmb sy(সিস্টেম) মেমরির বাধাগুলি সেই সংকলকটিতে ব্যবহার করে এই কোরএলসিআরআর আলোচনাটিও দেখুন ।

আমি দৃser়ভাবে বলছি যে অন্য কোনও আইএসএর জন্য কোনও সি ++ বাস্তবায়ন std::threadঅ-সুসংহত ক্যাশেগুলি দিয়ে কোর জুড়ে চলে না। আমার কাছে প্রমাণ নেই যে এ জাতীয় কোনও বাস্তবায়ন নেই, তবে এটি অত্যন্ত অসম্ভব বলে মনে হচ্ছে। আপনি যদি এইচডব্লিউটির কোনও নির্দিষ্ট বিদেশী অংশকে লক্ষ্য না করে থাকেন তবে আপনার কর্মক্ষমতা সম্পর্কে আপনার চিন্তাভাবনাটি সমস্ত থ্রেডের মধ্যে এমইএসআই-এর মতো ক্যাশে সামঞ্জস্যতা গ্রহণ করা উচিত। (যথাযথভাবে atomic<T>নির্ভুলতার গ্যারান্টি দেয় এমন উপায়ে ব্যবহার করুন !)


সুসংগত ক্যাশে এটি সহজ করে তোলে

তবে সুসংগত ক্যাশে সমেত একাধিক-মূল সিস্টেমে রিলিজ-স্টোর বাস্তবায়ন করার অর্থ এই সুতার স্টোরগুলির জন্য ক্যাশে প্রতিশ্রুতিবদ্ধ আদেশ দেওয়া, কোনও স্পষ্টভাবে ফ্লাশিং না করা। ( https://preshing.com/20120913/acquire-and-release-semantics/ এবং https://preshing.com/20120710/ মেমরি- বারিয়ারস- are-like - source- control - operations/ )। (এবং অধিগ্রহণ-বোঝার অর্থ অন্য কোরে ক্যাশে অ্যাক্সেসের আদেশ দেওয়া)।

একটি মেমোরি বাধা নির্দেশ কেবল স্ট্রিম বাফার ড্রেন না হওয়া অবধি বর্তমান থ্রেডের বোঝা এবং / অথবা স্টোরগুলিকে অবরুদ্ধ করে; যা সর্বদা নিজেরাই সম্ভব দ্রুত ঘটে। ( কোনও মেমোরি বাধা কী নিশ্চিত করে যে ক্যাশে সংহতি সম্পন্ন হয়েছে? এই ভ্রান্ত ধারণাকে সম্বোধন করে)। সুতরাং আপনার যদি অর্ডার দেওয়ার দরকার না হয় তবে কেবল অন্যান্য থ্রেডে প্রম্পট দৃশ্যমানতা mo_relaxedঠিক আছে। (এবং তাই volatile, তবে তা করবেন না))

আরও দেখুন সি / সি ++ 11 প্রসেসর থেকে ম্যাপিং

মজাদার ঘটনা: x86-এ, প্রতিটি এসএম স্টোরই একটি রিলিজ-স্টোর কারণ x86 মেমরি মডেলটি মূলত সিক-সিএসটি প্লাস একটি স্টোর বাফার (স্টোর ফরোয়ার্ডিং সহ)।


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

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

(x86 এর দৃ strongly়ভাবে অর্ডার করা এএসএম মেমোরি মডেলটির অর্থ হল যে volatileএক্স -86 on-এ আপনাকে আরও কাছাকাছি পৌঁছে দেবে mo_acq_rel, ব্যতীত অ-পারমাণবিক ভেরিয়েবলগুলির সাথে সংকলন-সময় পুনরায় ক্রমান্বিত হওয়া এখনও ঘটতে পারে But তবে বেশিরভাগ নন-এক্স ৮ weak মেমোরি মডেলগুলিকে দুর্বলভাবে অর্ডার করেছেন) volatileএবং relaxedপ্রায় হিসাবে দুর্বল mo_relaxed।)


মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
স্যামুয়েল লিউ

2
দুর্দান্ত লেখার আপ। এটি হ'ল আমি কেবল একটি কম্বল স্টেটমেন্টের পরিবর্তে ( সমস্ত তথ্য দিচ্ছি) সন্ধান করছিলাম যা কেবল "একক বিশ্বব্যাপী শেয়ারকৃত বুলিয়ান পতাকার জন্য অস্থির পরিবর্তে পরমাণু ব্যবহার করুন" বলেছিল।
বার্নি

2
@ বার্নি: বারবার দাবি করাতে হতাশ হয়ে আমি এটি লিখেছিলাম যে ব্যবহার না করা ক্যাশেatomic একই চলকটির জন্য বিভিন্ন থ্রেডের বিভিন্ন মান হতে পারে । / facepalm। ক্যাশে, না, সিপিইউতে হ্যাঁ নিবন্ধন করে (অ-পারমাণবিক ভেরিয়েবল সহ); সিপিইউগুলি সুসংগত ক্যাশে ব্যবহার করে। আমি চাই সিপিইউগুলি কীভাবে কাজ করে সে সম্পর্কে ভুল ধারণা ছড়িয়ে দেওয়ার জন্য এসও-তে অন্য প্রশ্নগুলির ব্যাখ্যায় পূর্ণ ছিল না । (কারণ পারফরম্যান্স কারণে বুঝতে এটি একটি দরকারী জিনিস, এবং আইএসও সি ++ পারমাণবিক নিয়মগুলি কেন সেভাবে লেখা হয় তা ব্যাখ্যা করতেও সহায়তা করে))atomic
পিটার

-1
#include <iostream>
#include <thread>
#include <unistd.h>
using namespace std;

bool checkValue = false;

int main()
{
    std::thread writer([&](){
            sleep(2);
            checkValue = true;
            std::cout << "Value of checkValue set to " << checkValue << std::endl;
        });

    std::thread reader([&](){
            while(!checkValue);
        });

    writer.join();
    reader.join();
}

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


4
এর সাথে কী করার আছে volatile? হ্যাঁ, এই কোডটি ইউবি - তবে এটির সাথে এটি ইউবিও রয়েছে volatile
ডেভিড শোয়ার্জ

-2

আপনার অস্থির এবং সম্ভবত লক করা দরকার।

অস্থিরতা অপটিমাইজারকে বলে যে মানটি ততক্ষণে অ্যাসিক্রোনালিকভাবে পরিবর্তিত হতে পারে

volatile bool flag = false;

while (!flag) {
    /*do something*/
}

লুপের চারপাশে প্রতিবার পতাকা পড়বে।

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

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


1
তবে এটি কি না, এবং অন্যান্য প্রতিক্রিয়াতে একই উদাহরণ, ব্যস্ত অপেক্ষা এবং এভাবে কিছু এড়ানো উচিত? এটি যদি স্বীকৃত উদাহরণ হয় তবে এমন বাস্তব জীবনের কোনও উদাহরণ রয়েছে যা স্বীকৃত নয়?
ডেভিড প্রেস্টন

7
@ ক্রিস: ব্যস্ত ওয়েটিং মাঝেমধ্যে একটি ভাল সমাধান। বিশেষত, আপনি যদি কেবল কয়েকটি ঘড়ির চক্রের জন্য অপেক্ষা করতে চান, তবে এটি থ্রেড স্থগিতকরণের অনেক বেশি হেভিওয়েট পদ্ধতির চেয়ে অনেক কম ওভারহেড বহন করবে। অবশ্যই, আমি অন্যান্য মন্তব্যে যেমন উল্লেখ করেছি, উদাহরণস্বরূপ এর ত্রুটিযুক্ত কারণ তারা ধরে নিয়েছে যে পতাকাটি পড়া / লেখার কোডটিকে সুরক্ষিত কোডের সাথে পুনরায় সাজানো হবে না এবং এরকম কোনও গ্যারান্টি দেওয়া হয়নি, এবং তাই , volatileএমনকি এই ক্ষেত্রে এমনকি দরকারী না। তবে ব্যস্ততা অপেক্ষা করা মাঝে মাঝে দরকারী কৌশল useful
জালফ

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

2
@ সিটিআরএলএইচটি-ওল্ডর: এটি volatile" নোর্ডারিং " এর অর্থ তা নয়। আপনি আশা করছেন এর অর্থ এই যে দোকানগুলি বিশ্বব্যাপী দৃশ্যমান হয়ে উঠবে (অন্যান্য থ্রেডগুলিতে) প্রোগ্রাম ক্রমে। এটিই আপনাকে atomic<T>দিয়ে দেয় memory_order_releaseবা seq_cstদেয়। তবে volatile কেবল আপনাকেই কোনও সংকলন-সময় পুনঃক্রমের গ্যারান্টি দেয় : প্রতিটি অ্যাক্সেস প্রোগ্রাম ক্রমে asm এ প্রদর্শিত হবে। একটি ডিভাইস ড্রাইভারের জন্য দরকারী। এবং বর্তমান কোর / থ্রেডে কোনও বিঘ্নিত হ্যান্ডলার, ডিবাগার, বা সিগন্যাল হ্যান্ডলারের সাথে ইন্টারঅ্যাক্ট করার জন্য দরকারী, তবে অন্যান্য কোরগুলির সাথে মিথস্ক্রিয়া করার জন্য নয়।
পিটার

1
volatileআপনি keep_runningএখানে করছেন এমন পতাকা চেক করার জন্য অনুশীলনে যথেষ্ট : রিয়েল সিপিইউতে সর্বদা সুসংগত ক্যাশে থাকে যা ম্যানুয়াল ফ্লাশিংয়ের প্রয়োজন হয় না। কিন্তু সুপারিশ কোন কারণে volatileউপর atomic<T>দিয়ে mo_relaxed; আপনি একই asm পাবেন।
পিটার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.