চঞ্চল ব্যয়বহুল?


111

অস্থির বাস্তবায়ন সম্পর্কে কম্পাইলার লেখকদের জন্য জেএসআর -133 কুকবুক পড়ার পরে , বিশেষত "পারমাণবিক নির্দেশাবলীর সাথে ইন্টারঅ্যাকশনস" বিভাগটি আমি ধরে নিয়েছি যে আপডেট না করে একটি উদ্বায়ী ভেরিয়েবলটি পড়ার জন্য একটি লোডলয়েড বা একটি লোডস্টোর বাধা প্রয়োজন। পৃষ্ঠার আরও নীচে আমি দেখতে পাচ্ছি যে লোডল্ড এবং লোডস্টোর কার্যকরভাবে এক্স 86 সিপিইউতে কোনও বিকল্প নেই। এর অর্থ কি এই যে x86 এ সুস্পষ্ট ক্যাশে অবৈধতা ছাড়াই অস্থির পাঠ্য অপারেশন করা যেতে পারে এবং এটি একটি সাধারণ পরিবর্তনশীল পঠনের মতোই দ্রুত (অস্থিরতার পুনরায় ক্রমবর্ধমান সীমাবদ্ধতা উপেক্ষা করে)?

আমি বিশ্বাস করি আমি এটি সঠিকভাবে বুঝতে পারি না। কেউ আমাকে আলোকিত করার জন্য যত্ন নিতে পারে?

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

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


1
আপনি উল্লেখ করেছেন একাধিক সিপিইউর কনফিগারেশন সম্পর্কে আমার সম্পাদনা। এটি ঘটতে পারে যে স্বল্পকালীন রেফারেন্সের জন্য মাল্টি সিপিইউ সিস্টেমে মূল মেমোরিতে একটি পঠন / লেখার জায়গা আর নেই।
জন ভিন্ট

2
অস্থির পড়া নিজেই ব্যয়বহুল নয়। মূল ব্যয় হ'ল এটি কীভাবে অপ্টিমাইজেশন প্রতিরোধ করে। অনুশীলনে সেই ব্যয়টি গড়পড়তাভাবে খুব বেশি হয় না, যদি না কোনও টান লুপে অস্থিরতা ব্যবহার করা হয়।
অপরিবর্তনীয়

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

উত্তর:


123

ইন্টেলে একটি অন-বিতর্কিত উদ্বোধন পঠন বেশ সস্তা। আমরা যদি নিম্নলিখিত সাধারণ কেসটি বিবেচনা করি:

public static long l;

public static void run() {        
    if (l == -1)
        System.exit(-1);

    if (l == -2)
        System.exit(-1);
}

জাভা 7 এর এসেম্বলি কোড প্রিন্ট করার ক্ষমতাটি ব্যবহার করে রান পদ্ধতিটি দেখতে এমন কিছু দেখাচ্ছে:

# {method} 'run2' '()V' in 'Test2'
#           [sp+0x10]  (sp of caller)
0xb396ce80: mov    %eax,-0x3000(%esp)
0xb396ce87: push   %ebp
0xb396ce88: sub    $0x8,%esp          ;*synchronization entry
                                    ; - Test2::run2@-1 (line 33)
0xb396ce8e: mov    $0xffffffff,%ecx
0xb396ce93: mov    $0xffffffff,%ebx
0xb396ce98: mov    $0x6fa2b2f0,%esi   ;   {oop('Test2')}
0xb396ce9d: mov    0x150(%esi),%ebp
0xb396cea3: mov    0x154(%esi),%edi   ;*getstatic l
                                    ; - Test2::run@0 (line 33)
0xb396cea9: cmp    %ecx,%ebp
0xb396ceab: jne    0xb396ceaf
0xb396cead: cmp    %ebx,%edi
0xb396ceaf: je     0xb396cece         ;*getstatic l
                                    ; - Test2::run@14 (line 37)
0xb396ceb1: mov    $0xfffffffe,%ecx
0xb396ceb6: mov    $0xffffffff,%ebx
0xb396cebb: cmp    %ecx,%ebp
0xb396cebd: jne    0xb396cec1
0xb396cebf: cmp    %ebx,%edi
0xb396cec1: je     0xb396ceeb         ;*return
                                    ; - Test2::run@28 (line 40)
0xb396cec3: add    $0x8,%esp
0xb396cec6: pop    %ebp
0xb396cec7: test   %eax,0xb7732000    ;   {poll_return}
;... lines removed

যদি আপনি গেসট্যাটিকের 2 টি রেফারেন্সের দিকে লক্ষ্য করেন তবে প্রথমটিতে মেমরি থেকে বোঝা যুক্ত হয়, দ্বিতীয়টি লোডটি এড়িয়ে যায় কারণ রেজিস্টার (গুলি) থেকে এটি পুনরায় ব্যবহার করা হয় এটি ইতিমধ্যে লোড হয় (দীর্ঘ হয় 64 বিট এবং আমার 32 বিট ল্যাপটপে এটি 2 নিবন্ধ ব্যবহার করে)।

যদি আমরা l পরিবর্তনশীলটিকে অস্থির করে তুলি তবে ফলস্বরূপ সমাবেশটি ভিন্ন।

# {method} 'run2' '()V' in 'Test2'
#           [sp+0x10]  (sp of caller)
0xb3ab9340: mov    %eax,-0x3000(%esp)
0xb3ab9347: push   %ebp
0xb3ab9348: sub    $0x8,%esp          ;*synchronization entry
                                    ; - Test2::run2@-1 (line 32)
0xb3ab934e: mov    $0xffffffff,%ecx
0xb3ab9353: mov    $0xffffffff,%ebx
0xb3ab9358: mov    $0x150,%ebp
0xb3ab935d: movsd  0x6fb7b2f0(%ebp),%xmm0  ;   {oop('Test2')}
0xb3ab9365: movd   %xmm0,%eax
0xb3ab9369: psrlq  $0x20,%xmm0
0xb3ab936e: movd   %xmm0,%edx         ;*getstatic l
                                    ; - Test2::run@0 (line 32)
0xb3ab9372: cmp    %ecx,%eax
0xb3ab9374: jne    0xb3ab9378
0xb3ab9376: cmp    %ebx,%edx
0xb3ab9378: je     0xb3ab93ac
0xb3ab937a: mov    $0xfffffffe,%ecx
0xb3ab937f: mov    $0xffffffff,%ebx
0xb3ab9384: movsd  0x6fb7b2f0(%ebp),%xmm0  ;   {oop('Test2')}
0xb3ab938c: movd   %xmm0,%ebp
0xb3ab9390: psrlq  $0x20,%xmm0
0xb3ab9395: movd   %xmm0,%edi         ;*getstatic l
                                    ; - Test2::run@14 (line 36)
0xb3ab9399: cmp    %ecx,%ebp
0xb3ab939b: jne    0xb3ab939f
0xb3ab939d: cmp    %ebx,%edi
0xb3ab939f: je     0xb3ab93ba         ;*return
;... lines removed

এক্ষেত্রে ভেরিয়েবল এল এর উভয় গেসট্যাটিক রেফারেন্সেই মেমরি থেকে বোঝা যুক্ত হয়, অর্থাত্ মানটি একাধিক অস্থির পাঠকের জুড়ে কোনও রেজিস্টারে রাখা যায় না। পারমাণবিক পড়ার মান রয়েছে কিনা তা নিশ্চিত করতে মূল স্মৃতি থেকে একটি এমএমএক্স রেজিস্টারে movsd 0x6fb7b2f0(%ebp),%xmm0পাঠ করা হয় যা রিড অপারেশনটিকে একক নির্দেশনা করে তোলে (পূর্ববর্তী উদাহরণ থেকে আমরা দেখেছি যে 64৪ বিট মানটিতে সাধারণত একটি 32 বিট সিস্টেমে দুটি 32 বিট রিডের প্রয়োজন হয়)।

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


পার্শ্ব দ্রষ্টব্য, জাভা 6 তে সমাবেশ দেখানোর মতো ক্ষমতা রয়েছে (এটি হটস্পট যা এটি করে)
বেটসেস

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

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

20

সাধারণভাবে বলতে গেলে, বেশিরভাগ আধুনিক প্রসেসরগুলিতে একটি উদ্বায়ী লোড একটি সাধারণ লোডের সাথে তুলনীয়। একটি অস্থির স্টোর মন্টিওর-এন্ট্রি / মনিটর-প্রস্থানের সময় প্রায় 1/3 এটি ক্যাশে সুসংগত এমন সিস্টেমে দেখা যায়।

ওপি-র প্রশ্নের উত্তরের জন্য, অস্থির লেখাগুলি ব্যয়বহুল, তবে পাঠাগুলি সাধারণত হয় না।

এর অর্থ কি এই যে অস্থির পাঠের অপারেশনগুলি x86 এ স্পষ্ট ক্যাশে অবৈধতা ছাড়াই করা যেতে পারে এবং এটি একটি সাধারণ পরিবর্তনশীল পঠনের মতোই দ্রুত (অস্থিরতার পুনরায় সাজানো নিয়ন্ত্রণগুলি উপেক্ষা করে)?

হ্যাঁ, কখনও কখনও কোনও ক্ষেত্রটি বৈধতা দেওয়ার সময় সিপিইউ মূল স্মৃতিতেও আঘাত না করে পরিবর্তে অন্যান্য থ্রেড ক্যাশে গুপ্তচরবৃত্তি করে সেখান থেকে মান পেতে পারে (খুব সাধারণ ব্যাখ্যা)।

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

ওপির সম্পাদনার উত্তর দিতে সম্পাদনা করুন:

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

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


5
একটি অ্যাটমিক রেফারেন্সটি হ'ল একটি অস্থির ক্ষেত্রের জন্য একটি আবরণ যা দেশীয় ফাংশনগুলি যেমন getAndSet, তুলনাআন্ডসেট ইত্যাদি অতিরিক্ত কার্যকারিতা সরবরাহ করে, সুতরাং এটির ব্যবহারের পারফরম্যান্সের দৃষ্টিভঙ্গি থেকে যদি আপনাকে যুক্ত কার্যকারিতা প্রয়োজন হয় তবে এটি কার্যকর। তবে আমি ভাবছি আপনি এখানে ওএসকে কেন উল্লেখ করছেন? কার্যকারিতা সরাসরি সিপিইউ অপকডগুলিতে প্রয়োগ করা হয়। এবং এটি কি বোঝায় যে মাল্টি প্রসেসর সিস্টেমগুলিতে, যেখানে একটি সিপিইউতে অন্যান্য সিপিইউগুলির ক্যাশে বিষয়গুলি সম্পর্কে কোনও জ্ঞান নেই যে সিপিইউ সবসময় প্রধান স্মৃতিতে আঘাত করতে হয় কারণ উদ্বায়ী ধীর হয়?
ড্যানিয়েল

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

@ জন, আপনি কেন পারমাণবিক রেফারেন্সের মাধ্যমে আরেকটি নির্দেশনা যুক্ত করবেন? আপনার যদি সিএএস দরকার হয় - ঠিক আছে তবে অ্যাটমিকআপডেটর আরও ভাল বিকল্প হতে পারে। যতদূর আমি এটমিক রেফারেন্স সম্পর্কে কোনও অন্তঃসত্ত্বা স্মরণ করি না।
17:37

@ বেস্টসেস সমস্ত সাধারণ পার্পাউজগুলিতে আপনার ঠিক আছে যে এটমিক রেফারেন্স.সেট / গেট এবং অস্থির লোড এবং স্টোরের মধ্যে কোনও পার্থক্য নেই। যা বলা হচ্ছে আমি কখন ব্যবহার করব সে সম্পর্কে আমার একই অনুভূতি ছিল (এবং কিছুটা করতে হবে)। এই প্রতিক্রিয়াটি এটিকে কিছুটা বিশদ জানাতে পারে stackoverflow.com/questions/3964317/… । উভয়ই ব্যবহারকে অগ্রাধিকার দেওয়া হয়, সাধারণ অস্থিরতার উপরে অ্যাটমিকরেফারেন্স ব্যবহারের জন্য আমার একমাত্র যুক্তি পরিষ্কার ডকুমেন্টেশনের জন্য - যা নিজেই সবচেয়ে বড় যুক্তিটিই বুঝতে পারি না হয় আমি বুঝতে পেরেছি
জন ভিন্ট

একদিকে লক্ষ্য করুন কিছু একটি অস্থির ক্ষেত্র / অ্যাটমিক রেফারেন্স (কোনও সিএএসের প্রয়োজন ছাড়াই) ব্যবহার করে বগি কোডটি পুরনো ন্যানব্লা.কমের
জন ভিন্ট

12

জাভা মেমোরি মডেলের ভাষায় (জেএসআর 133-তে জাভা 5+ এর জন্য সংজ্ঞায়িত) কোনও volatileভেরিয়েবলের যে কোনও ক্রিয়াকলাপ - পড়ুন বা লিখুন - একই ভেরিয়েবলের সাথে অন্য কোনও ক্রিয়াকলাপের ক্ষেত্রে সম্মতিযুক্ত হওয়ার আগে সম্পর্ক তৈরি করে । এর অর্থ হ'ল সংকলক এবং জেআইটি নির্দিষ্ট থিমের মধ্যে নির্দেশাবলী পুনরায় অর্ডার করা বা কেবল স্থানীয় ক্যাশে অভ্যন্তরীণ ক্রিয়াকলাপের মতো নির্দিষ্ট আশাবাদ এড়াতে বাধ্য হয় are

যেহেতু কিছু অপটিমাইজেশন উপলব্ধ নেই, ফলস্বরূপ কোডটি ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে কম না হলেও এটি হতে পারে।

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


4

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

আরও সাধারণভাবে, একটি বহু-প্রসেসর সিস্টেমে আমি দেখতে পাই না যে কীভাবে একটি উদ্বায়ী ভেরিয়েবলের অ্যাক্সেস পেনাল্টি ছাড়াই করা যেতে পারে - প্রসেসর এ একটি লেখার প্রসেসর বি-তে একটি রিডের সাথে সিঙ্ক্রোনাইজ করা হবে তা নিশ্চিত করার কিছু উপায় থাকতে হবে must


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

12
-১, একটি সিঙ্ক্রোনাইজড ব্লক ব্যবহারের চেয়ে অস্থির পরিবর্তনশীল অ্যাক্সেস করা কিছুটা আলাদা। একটি সিঙ্ক্রোনাইজড ব্লকে প্রবেশের জন্য লকটি বের করার জন্য একটি পারমাণবিক তুলনা এবং সেটসেট ভিত্তিক লেখার প্রয়োজন হয় এবং এটি প্রকাশের জন্য একটি উদ্বায়ী লেখার প্রয়োজন। যদি লকটি সন্তুষ্ট থাকে তবে লকটি সালিশ করতে নিয়ন্ত্রণটি ব্যবহারকারীর স্থান থেকে কার্নেল স্পেসে যেতে হবে (এটি ব্যয়বহুল বিট)। একটি অস্থির অ্যাক্সেস সর্বদা ব্যবহারকারীর স্থানে থাকবে।
মাইকেল বার্কার

@ মিশেল বার্কার: আপনি কি নিশ্চিত যে সমস্ত মনিটরের কার্নেল দ্বারা রক্ষা করা উচিত অ্যাপ্লিকেশনটি নয়?
ড্যানিয়েল

@ ড্যানিয়েল: আপনি যদি একটি সিঙ্ক্রোনাইজড ব্লক বা লক ব্যবহার করে কোনও মনিটরের প্রতিনিধিত্ব করেন তবে হ্যাঁ, তবে কেবল যদি মনিটরটি সন্তুষ্ট থাকে। কার্নেল আরবিট্রেশন ছাড়াই এটি করার একমাত্র উপায় হ'ল থ্রেড পার্কিংয়ের পরিবর্তে ব্যস্ত স্পিন একই যুক্তি ব্যবহার করা।
মাইকেল বার্কার

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