ফিফোর জন্য আমার কোন এসটিএল ধারক ব্যবহার করা উচিত?


94

কোন এসটিএল কনটেইনারটি আমার প্রয়োজনগুলি সবচেয়ে ভাল ফিট করে? আমার মূলত একটি 10 ​​টি উপাদান প্রশস্ত কন্টেইনারে রয়েছে যাতে আমি প্রাচীনতম উপাদানটি (প্রায় এক মিলিয়ন সময়) আইএন করার push_backসময় ক্রমাগতভাবে নতুন উপাদান থাকে pop_front

আমি বর্তমানে টাস্কটির জন্য একটি ব্যবহার করছি তবে আমি ভাবছিলাম যে এগুলি আরও দক্ষ হবে std::dequeকিনা std::listযেহেতু আমার নিজেকে পুনর্বিবেচনার প্রয়োজন হবে না (বা সম্ভবত আমি একটির std::dequeজন্য ভুল করছি std::vector?)। বা আমার প্রয়োজনের জন্য আরও কার্যকর কন্টেইনার আছে?

PS আমার এলোমেলো অ্যাক্সেসের দরকার নেই


4
আপনার প্রয়োজনের জন্য কোনটি দ্রুততর হয় তা দেখার জন্য এবং সময় দিয়ে কেন চেষ্টা করবেন না?
কেটিসি

4
আমি এটি করতে চলেছিলাম, তবে আমি পাশাপাশি একটি তাত্ত্বিক উত্তরও খুঁজছিলাম।
গ্যাব রয়ের

4
std::dequereallocate করা হবে না। এটি একটি এর হাইব্রিড std::listএবং std::vectorএটি যেখানে এটির চেয়ে বড় অংশগুলি বরাদ্দ করে std::listতবে এটি আর এর মতো পুনরায় প্রকাশ করবে না std::vector
ম্যাট প্রাইস

4
না, মান থেকে প্রাসঙ্গিক গ্যারান্টিটি এখানে রয়েছে: "ডীকের শুরুতে বা শেষে কোনও একক উপাদান সন্নিবেশ করাতে সর্বদা নিয়মিত সময় লাগে এবং টি এর অনুলিপি নির্মাণকারীকে একটি কল দেয় call"
ম্যাট দাম

4
@ জন: না, এটি আবার বরাদ্দ করে। হতে পারে আমরা কেবল পদগুলি মিশ্রিত করছি। আমি মনে করি রিলোকেট বলতে পুরানো বরাদ্দ নেওয়া, এটি একটি নতুন বরাদ্দে অনুলিপি করা এবং পুরানোটি বাতিল করা।
GManNickG

উত্তর:


201

যেহেতু উত্তরগুলির একটি অগণিত আছে, আপনি বিভ্রান্ত হতে পারেন, তবে সংক্ষেপে:

ব্যবহার ক std::queue। এর কারণটি সহজ: এটি একটি ফিফো কাঠামো। আপনি ফিফো চান, আপনি একটি ব্যবহার করুন std::queue

এটি আপনার উদ্দেশ্য অন্য কারও কাছে এবং এমনকি নিজের কাছে পরিষ্কার করে দেয়। ক std::listবা std::dequeনা। একটি তালিকা যে কোনও জায়গায় sertোকাতে এবং মুছে ফেলতে পারে, যা কোনও ফিফো কাঠামোটি করণীয় বলে মনে করে না, এবং এটি dequeউভয় প্রান্ত থেকে যোগ এবং সরিয়ে ফেলতে পারে, যা ফিফোর কাঠামো কিছু করতে পারে না।

এজন্য আপনার একটি ব্যবহার করা উচিত queue

এখন, আপনি অভিনয় সম্পর্কে জিজ্ঞাসা করেছেন। প্রথমত, সর্বদা থাম্বের এই গুরুত্বপূর্ণ নিয়মটি মনে রাখবেন: ভাল কোড আগে, শেষ পারফরম্যান্স।

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

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

যা সব বলেছিল, std::queueএটি কেবলমাত্র একটি অ্যাডাপ্টার। এটি নিরাপদ ইন্টারফেস সরবরাহ করে তবে অভ্যন্তরে একটি পৃথক ধারক ব্যবহার করে। আপনি এই অন্তর্নিহিত ধারকটি চয়ন করতে পারেন এবং এটি নমনীয়তার একটি ভাল ব্যবসার অনুমতি দেয়।

সুতরাং, আপনার কোন অন্তর্নিহিত ধারক ব্যবহার করা উচিত? আমরা সেটা জানি std::listএবং std::dequeউভয় প্রয়োজনীয় ফাংশন প্রদান করেন ( push_back(), pop_front(), এবং front()), তাই কীভাবে আমরা স্থির করবেন?

প্রথমত, বুঝতে হবে যে মেমরি বরাদ্দকরণ (এবং deallocating) করা কোনও দ্রুত কাজ নয়, সাধারণত, কারণ এটিতে ওএসে বেরিয়ে আসা এবং এটি কিছু করার জন্য জিজ্ঞাসা করা জড়িত। একটি listমেমরি প্রতি একক সময় কিছু যোগ করা হয় বরাদ্দ, এবং এটি ডি-এলোকেট যখন এটি দূরে যায় করা হয়েছে।

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

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

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

এটি তালিকার বিপরীতে, যেখানে ডেটা একসাথে একবারে বরাদ্দ করা হয়। এর অর্থ মেমরির সমস্ত জায়গায় ডেটা ছড়িয়ে দেওয়া যেতে পারে এবং ক্যাশের কার্যকারিতা খারাপ হবে।

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

তবে মনে রাখবেন: একটি ক্লিন ইন্টারফেসের সাথে কোডটি কাজ করুন, তারপরে পারফরম্যান্স সম্পর্কে চিন্তিত।

জন উদ্বেগ উত্থাপন করে যে একটি listবা মোড়ানো dequeএকটি কার্যকারিতা হ্রাস ঘটায়। আবার, তিনি বা আমি নিজেরাই এটির প্রোফাইল না দিয়ে নির্দিষ্ট করে বলতে পারি, তবে সম্ভাবনা হ'ল সংকলক যে কলগুলি করবে সেগুলি ইনলাইন করবে queue। এটি হ'ল, যখন আপনি বলবেন queue.push(), এটি সত্যিই কেবল বলে দেবে queue.container.push_back(), ফাংশন কলটি পুরোপুরি বাদ দেওয়া।

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


10
+1 - এবং যদি এটি প্রমাণিত হয় যে :: বৃত্তাকার_বফার <> এর সর্বোত্তম পারফরম্যান্স রয়েছে তবে কেবল এটি অন্তর্নিহিত ধারক হিসাবে ব্যবহার করুন (এটি প্রয়োজনীয় পুশ_ব্যাক (), পপ_ফ্রন্ট (), সামনের () এবং পিছনেও সরবরাহ করে) )।
মাইকেল বুড়

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

4
সমস্যা সমাধান না করার জন্য -1 এবং ফুল ফোটানো অকেজো উত্তর। এখানে ডান উত্তর সংক্ষিপ্ত এবং এটি উত্সাহিত :: বৃত্তাকার_বফার <>।
দিমিত্রি চিচকভ

4
"প্রথমে ভাল কোড, পারফরম্যান্স শেষ", এটি দুর্দান্ত একটি উদ্ধৃতি। যদি সকলেই এটি বুঝতে পারে তবে :)
থ্রিগ্রিনড্রয়েড

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

28

চেক আউট std::queue। এটি একটি অন্তর্নিহিত ধারক প্রকারটি মোড়ানো এবং ডিফল্ট ধারক std::deque


4
কম্পাইলার দ্বারা প্রতিটি অতিরিক্ত স্তর মুছে ফেলা হবে । আপনার যুক্তি অনুসারে, আমাদের সকলকে কেবল সমাবেশে প্রোগ্রাম করা উচিত, যেহেতু ভাষাটি কেবল একটি শেল যা পথে চলে। পয়েন্টটি হ'ল কাজের জন্য সঠিক ধরণটি ব্যবহার করা। এবং queueযে টাইপ। ভাল কোড আগে, পরে কর্মক্ষমতা। হেল, বেশিরভাগ পারফরম্যান্সই প্রথম স্থানে ভাল কোড ব্যবহার করেই আসে।
GManNickG

4
অস্পষ্ট হওয়ার জন্য দুঃখিত - আমার বক্তব্যটি হ'ল যে একটি সারি প্রশ্নটি জিজ্ঞাসা করছে ঠিক তাই, এবং সি ++ ডিজাইনাররা ভেবেছিলেন যে এই ব্যবহারের ক্ষেত্রে ডিক একটি ভাল অন্তর্নিহিত ধারক ছিল।
মার্ক র্যানসোম

4
এই পারফরম্যান্সের অভাব খুঁজে পেয়েছেন এমনটি বোঝানোর জন্য এই প্রশ্নের কিছু নেই। তাদের প্রাথমিক সমাধানটি গ্রহণযোগ্যভাবে সম্পাদন করে কিনা তা নির্বিশেষে অনেক শিক্ষানবিস ক্রমাগত যে কোনও সমস্যার সর্বাধিক কার্যকর সমাধান সম্পর্কে জিজ্ঞাসা করছেন।
jalf

4
@ জন, যদি তিনি পারফরম্যান্সের অভাব দেখতে পান তবে সুরক্ষার শেল সরিয়ে দেওয়ার queueফলে কর্মক্ষমতা বাড়বে না, যেমনটি আমি বলছিলাম। আপনি একটি প্রস্তাব দিয়েছেন list, যা সম্ভবত আরও খারাপ সম্পাদন করবে।
GManNickG

4
স্ট্যান্ড :: কাতারে <> বিষয়টি হ'ল যদি ডিকু <> আপনি যা চান না (পারফোলেন্স বা যে কোনও কারণেই), এটি ব্যাক স্টোর হিসাবে স্টাড :: তালিকা ব্যবহার করার জন্য এটি পরিবর্তন করার জন্য এক-লাইনার - জিমন আবার ফিরে বলল। এবং যদি আপনি সত্যিই কোনও তালিকার পরিবর্তে একটি রিং বাফার ব্যবহার করতে চান তবে বুস্ট :: সার্কুলার_বাফার <> ডানদিকে নেমে যাবে ... স্ট্যান্ড :: ক্যু <> প্রায় অবশ্যই 'ইন্টারফেস' যা ব্যবহার করা উচিত। এর জন্য ব্যাকিং স্টোরটি ইচ্ছায় বেশ পরিবর্তন করা যেতে পারে।
মাইকেল বারার


7

আমি প্রাচীনতম উপাদানটি প্রায় ইনকয়ের push_backসময় নিয়মিতভাবে নতুন উপাদানগুলি pop_front(প্রায় এক মিলিয়ন সময়)।

একটি মিলিয়ন আসলে কম্পিউটারে বড় সংখ্যা নয়। অন্যরা std::queueযেমন পরামর্শ দিয়েছে, আপনার প্রথম সমাধান হিসাবে এটি ব্যবহার করুন । এটি খুব ধীর হওয়ার সম্ভাবনা না থাকলে, কোনও প্রোফাইলার ব্যবহার করে বাধাটি চিহ্নিত করুন (অনুমান করবেন না!) এবং একই ইন্টারফেসের সাহায্যে একটি ভিন্ন ধারক ব্যবহার করে পুনরায় বাস্তবায়ন করুন।


4
ভাল কথাটি হ'ল এটি একটি বড় সংখ্যা যা আমি করতে চাই তা রিয়েল টাইম হওয়ার কথা। যদিও আপনি ঠিক বলেছেন যে কারণটি সনাক্ত করার জন্য আমার একজন প্রোফাইলার ব্যবহার করা উচিত ছিল ...
গ্যাব রয়ের

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

@ গ্যাব: আপনার কোন ভিএস ২০০৮ আছে (এক্সপ্রেস, প্রো ...)? কেউ কেউ প্রোফাইলার নিয়ে আসে।
এসবিআই

@ গ্যাব দুঃখিত, আমি আর ভিএস ব্যবহার করি না তাই সত্যিই পরামর্শ দেওয়া যায় না

@ এসবিআই, আমি যা দেখছি তা থেকে এটি কেবলমাত্র টিম সিস্টেম সংস্করণে (যার কাছে আমার অ্যাক্সেস রয়েছে)। আমি এটি খতিয়ে দেখব।
গ্যাব রয়ের


3

একটি সারি সম্ভবত একটি ডেকের চেয়ে সহজ ইন্টারফেস তবে এ জাতীয় ছোট তালিকার জন্য, পারফরম্যান্সের পার্থক্য সম্ভবত নগণ্য।

একই তালিকাতে যায় । এটি আপনি কী এপিআই চান তার একটি পছন্দ নীচে।


তবে আমি ভাবছিলাম যে ধ্রুব ধাক্কা ব্যাক কিউগুলি তৈরি করছে বা ডিউকটি নিজেকে পুনর্বিবেচিত করছে
গ্যাব রয়ের

std :: কিউ হ'ল অন্য ধারকের চারপাশে একটি মোড়ক, সুতরাং একটি ডীককে মোড়ানো একটি সারি একটি কাঁচা ডিকের চেয়ে কম দক্ষ হবে।
জন মিলিকিন

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

4
@ জন: আমি চাই আপনি আমাকে এমন একটি মানদণ্ড দেখান যা এমন পারফরম্যান্সের পার্থক্য প্রদর্শন করে। এটি কোনও কাঁচা ডেকির চেয়ে কম দক্ষ নয়। সি ++ কম্পাইলাররা খুব আক্রমণাত্মকভাবে ইনলাইন করে।
জাল্ফ

4
আমি চেষ্টা করেছি। : ডি.এ. কুইক এবং নোংরা 10 উপাদানগুলির ধারক যার সাথে 100,000,000 পপ_ফ্রন্ট () এবং পুশ_ব্যাক () র্যান্ড () ইন্টি নম্বর সহ ভিসি 9-তে গতির জন্য রিলিজ বিল্ড দেয়: তালিকা (27), সারি (6), ডেক (6), অ্যারে (8) ।
কেটিসি

0

একটি ব্যবহার করুন std::queue, তবে দুটি স্ট্যান্ডার্ড Containerশ্রেণীর পারফরম্যান্স ট্রেড অফ সম্পর্কে সচেতন হন ।

ডিফল্টরূপে, এর std::queueউপরে একটি অ্যাডাপ্টার std::deque। সাধারণত, এটি আপনার কার্যকারিতাটি দেবে যেখানে আপনার সংখ্যার অনেকগুলি সারি রয়েছে যাতে প্রচুর পরিমাণে এন্ট্রি থাকে, যা তাত্ক্ষণিকভাবে সাধারণ ক্ষেত্রে।

তবে, স্টাড :: ডিউক বাস্তবায়নে অন্ধ হবেন না । বিশেষত:

"... ডিউকের সাধারণত বড় ন্যূনতম মেমোরির ব্যয় থাকে; কেবল একটি উপাদানকে ধারণ করে এমন একটি ডীককে তার সম্পূর্ণ অভ্যন্তরীণ অ্যারে বরাদ্দ করতে হয় (যেমন 64৪-বিট লিবস্টেডসি ++ এর উপরে বস্তুর আকারের 8 গুণ; বস্তুর আকারের 16 গুণ বা 4096 বাইট, যেটি বড় হয়) , 64-বিট libc ++ তে)।

এটিকে নেট করার জন্য, ধরে নেওয়া যাক যে একটি সারি এন্ট্রি এমন একটি জিনিস যা আপনি সারি করতে চান, অর্থাত্ যথাযথ আকারে ছোট, তারপরে আপনার যদি 4 টি সারি থাকে, যার প্রত্যেকটিতে 30,000 এন্ট্রি থাকে, std::dequeবাস্তবায়নটি পছন্দনীয় বিকল্পের বিকল্প হবে। বিপরীতে, যদি আপনার 30,000 সারি থাকে, যার প্রত্যেকটিতে 4 টি এন্ট্রি রয়েছে, তবে সম্ভবত std::listবাস্তবায়নটি সর্বোত্তম হবে, কারণ আপনি কখনই সেই দৃশ্যে ওভারহেডকে ছোট করবেন না std::deque

ক্যাশে কীভাবে বাদশাহ, স্ট্রোস্ট্রুপ লিঙ্কযুক্ত তালিকাগুলি ইত্যাদিকে কীভাবে ঘৃণা করে সে সম্পর্কে প্রচুর মতামত পড়বেন এবং সেগুলি নির্দিষ্ট পরিস্থিতিতে কিছু সত্য। কেবল অন্ধ বিশ্বাসের ভিত্তিতে এটি গ্রহণ করবেন না, কারণ আমাদের দ্বিতীয় দৃশ্যে, এটি ডিফল্ট std::dequeবাস্তবায়ন কার্যকর হওয়ার সম্ভাবনা খুব কম । আপনার ব্যবহার এবং পরিমাপের মূল্যায়ন করুন।


-1

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

// FIFO with circular buffer
#define fifo_size 4

class Fifo {
  uint8_t buff[fifo_size];
  int writePtr = 0;
  int readPtr = 0;
  
public:  
  void put(uint8_t val) {
    buff[writePtr%fifo_size] = val;
    writePtr++;
  }
  uint8_t get() {
    uint8_t val = NULL;
    if(readPtr < writePtr) {
      val = buff[readPtr%fifo_size];
      readPtr++;
      
      // reset pointers to avoid overflow
      if(readPtr > fifo_size) {
        writePtr = writePtr%fifo_size;
        readPtr = readPtr%fifo_size;
      }
    }
    return val;
  }
  int count() { return (writePtr - readPtr);}
};

কিন্তু কখন / কখন তা ঘটবে?
ব্যবহারকারী 10658782

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