বুস্ট :: ফ্ল্যাট_ম্যাপ এবং মানচিত্র এবং আনর্ডার্ড_ম্যাপের তুলনায় এর কার্য সম্পাদন


103

প্রোগ্রামিংয়ে এটি সাধারণ জ্ঞান যা মেমরি লোকাল ক্যাশে হিটগুলির কারণে কর্মক্ষমতা অনেক উন্নত করে। আমি সম্প্রতি আবিষ্কার করেছি boost::flat_mapযা কোন মানচিত্রের ভেক্টর ভিত্তিক বাস্তবায়ন। এটি আপনার সাধারণ হিসাবে প্রায় জনপ্রিয় বলে মনে হচ্ছে না map/ unordered_mapতাই আমি কোনও পারফরম্যান্সের তুলনা খুঁজে পাইনি। এটি কীভাবে তুলনা করে এবং এর জন্য সর্বোত্তম ব্যবহারের ক্ষেত্রে কী কী?

ধন্যবাদ!


গুরুত্বপূর্ণ যে boost.org/doc/libs/1_70_0/doc/html/boost/container/… দাবী র্যান্ডম সন্নিবেশ লোগারিথমিক সময় লাগে, একটি উত্সাহিত বোঝা :: ফ্ল্যাট_ম্যাপ (এন এলোমেলো উপাদান সন্নিবেশ করে) লাগে O (n লগ এন) ) সময়। এটি মিথ্যা কথা, যেমন নীচে @ ভি.ডি.ডিউউ এর উত্তর গ্রাফ থেকে স্পষ্ট বোঝা যাচ্ছে: এলোমেলো inোকানো হে (এন) হয়, এবং এর মধ্যে এন ও (এন ^ 2) সময় নেয়।
ডন হ্যাচ

@ ডনহ্যাচ এখানে কীভাবে রিপোর্ট করবেন: github.com/boostorg/container/issues ? (এটি তুলনা সংখ্যার একটি গণনা দিতে পারে, তবে
চালচক্রের

উত্তর:


188

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

স্থির করা মাপকাঠি

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

1) আপনার ক্যাশে ওয়ার্মিং সম্পর্কে বিবেচনা করা উচিত

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

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

2) আরডিটিএসসি নির্ভুলতা পরিমাপ

আমি এটি করার পরামর্শও দিচ্ছি:

u64 g_correctionFactor;  // number of clocks to offset after each measurement to remove the overhead of the measurer itself.
u64 g_accuracy;

static u64 const errormeasure = ~((u64)0);

#ifdef _MSC_VER
#pragma intrinsic(__rdtsc)
inline u64 GetRDTSC()
{
    int a[4];
    __cpuid(a, 0x80000000);  // flush OOO instruction pipeline
    return __rdtsc();
}

inline void WarmupRDTSC()
{
    int a[4];
    __cpuid(a, 0x80000000);  // warmup cpuid.
    __cpuid(a, 0x80000000);
    __cpuid(a, 0x80000000);

    // measure the measurer overhead with the measurer (crazy he..)
    u64 minDiff = LLONG_MAX;
    u64 maxDiff = 0;   // this is going to help calculate our PRECISION ERROR MARGIN
    for (int i = 0; i < 80; ++i)
    {
        u64 tick1 = GetRDTSC();
        u64 tick2 = GetRDTSC();
        minDiff = std::min(minDiff, tick2 - tick1);   // make many takes, take the smallest that ever come.
        maxDiff = std::max(maxDiff, tick2 - tick1);
    }
    g_correctionFactor = minDiff;

    printf("Correction factor %llu clocks\n", g_correctionFactor);

    g_accuracy = maxDiff - minDiff;
    printf("Measurement Accuracy (in clocks) : %llu\n", g_accuracy);
}
#endif

এটি একটি তাত্ক্ষণিক পরিমাপক এবং সময়ে সময়ে একটি -10 ** 18 (b৪ বিট প্রথম নেগেটিভ মান) পেতে এড়াতে এটি সমস্ত পরিমাপ করা মানগুলির সর্বনিম্ন গ্রহণ করবে।

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

3) পরামিতি

শেষ সমস্যাটি হ'ল লোকেরা সাধারণত দৃশ্যের খুব কম পরিবর্তনের জন্য পরীক্ষা করে। একটি ধারক কর্মক্ষমতা দ্বারা প্রভাবিত হয়:

  1. বরাদ্দকরণ
  2. রয়েছে টাইপ আকার
  3. অনুলিখিত প্রকারের অনুলিপি অপারেশন, অ্যাসাইনমেন্ট অপারেশন, মুভ অপারেশন, নির্মাণ অপারেশন বাস্তবায়নের ব্যয়।
  4. পাত্রে উপাদানগুলির সংখ্যা (সমস্যার আকার)
  5. প্রকারের তুচ্ছ 3.-অপারেশন রয়েছে
  6. টাইপ হ'ল পিওডি

পয়েন্ট 1 গুরুত্বপূর্ণ কারণ কনটেইনাররা সময়ে সময়ে বরাদ্দ দেয় এবং সিআরটি "নতুন" বা কিছু ব্যবহারকারীর সংজ্ঞায়িত অপারেশন যেমন পুল বরাদ্দ বা ফ্রিলিস্ট বা অন্যান্য ব্যবহার করে বরাদ্দ করে তবে তা অনেকটাই গুরুত্বপূর্ণ ...

( পিটি 1 সম্পর্কে আগ্রহী লোকদের জন্য, সিস্টেম বরাদ্দকারীর কার্যকারিতা প্রভাব সম্পর্কে গেমদেবের রহস্য থ্রেডে যোগ দিন )

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

পয়েন্ট 3 পয়েন্ট 2 এর সমান, এটি কোনও ওজন ফ্যাক্টরের দ্বারা ব্যয়কে বহুগুণ বাদ দেয়।

পয়েন্ট 4 হ'ল ক্যাশে ইস্যুতে মিশ্রিত বড় ও একটি প্রশ্ন। কিছু খারাপ-জটিলতার পাত্রে খুব কম সংখ্যক প্রকারের জন্য কম-জটিলতার পাতাগুলি ছাড়িয়ে যেতে পারে (যেমন mapবনাম vector, কারণ তাদের ক্যাশে স্থানীয় অবস্থান ভাল, তবে mapস্মৃতিটিকে টুকরো টুকরো করে)। এবং তারপরে কোনও ক্রসিং পয়েন্টে, তারা হারাবে, কারণ অন্তর্ভুক্ত সামগ্রিক আকারটি মূল স্মৃতিতে "ফাঁস" হতে শুরু করে এবং ক্যাশে অনুপস্থিত কারণ, অ্যাসিম্পটোটিক জটিলতা অনুভূত হওয়া শুরু হতে পারে।

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

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

ফ্ল্যাট মানচিত্র সম্পর্কে

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

এটি এখনও অর্ডারযুক্ত ধারক। বেশিরভাগ লোকের সাধারণত ক্রম অংশ প্রয়োজন হয় না, তাই অস্তিত্ব unordered..

আপনি বিবেচনা করেছেন যে সম্ভবত আপনার একটি প্রয়োজন flat_unorderedmap? যা এমন কিছু google::sparse_mapবা এর মতো কিছু হবে। একটি খোলা ঠিকানা হ্যাশ ম্যাপ।

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

একটি খোলা ঠিকানা হ্যাশ ম্যাপে পুনঃস্থাপনের মানদণ্ডটি যখন ক্ষমতাটি লোড ফ্যাক্টরের দ্বারা গুণিত বালতি ভেক্টরের আকারকে ছাড়িয়ে যায়।

একটি সাধারণ লোড ফ্যাক্টর হ'ল 0.8; অতএব, আপনার এটির যত্ন নেওয়া দরকার, যদি আপনি নিজের হ্যাশ মানচিত্রটি পূরণের আগে প্রাক আকার করতে পারেন তবে সর্বদা এটির প্রাক-আকার: intended_filling * (1/0.8) + epsilonএটি আপনাকে পূরণের সময় সমস্ত কিছু তাত্পর্যপূর্ণভাবে পুনঃস্থাপন এবং পুনরায় কপি না করার গ্যারান্টি দেয়।

বদ্ধ ঠিকানা মানচিত্রের সুবিধা ( std::unordered..) হ'ল আপনাকে সেই পরামিতিগুলি সম্পর্কে যত্ন নিতে হবে না।

তবে এটি boost::flat_mapএকটি আদেশযুক্ত ভেক্টর; অতএব, এটিতে সর্বদা লগ (এন) অ্যাসিপটোটিক জটিলতা থাকবে যা খোলা ঠিকানার হ্যাশ মানচিত্রের (এমরোটাইজড ধ্রুবক সময়) এর চেয়ে কম ভাল। আপনার এটিও বিবেচনা করা উচিত।

বেঞ্চমার্ক ফলাফল

এটি বিভিন্ন মানচিত্রের ( intকী এবং __int64/ somestructমান হিসাবে) এবং এর সাথে জড়িত একটি পরীক্ষা std::vector

পরীক্ষিত প্রকারের তথ্য:

typeid=__int64 .  sizeof=8 . ispod=yes
typeid=struct MediumTypePod .  sizeof=184 . ispod=yes

সন্নিবেশ

সম্পাদনা করুন:

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

10000 এলোমেলো .োকান

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

মানচিত্র: ও (এন * লগ (এন))
হ্যাশম্যাপস: ও (এন)
ভেক্টর এবং ফ্ল্যাটম্যাপস: ও (এন * এন)

সতর্কবাণী : এর জন্য পরকালে 2 পরীক্ষার std::mapএবং উভয় flat_mapগুলি করছে বগী এবং আসলে পরীক্ষা আদেশ সন্নিবেশ (বনাম অন্যান্য পাত্রে জন্য র্যান্ডম সন্নিবেশ হ্যাঁ এটা দুঃখিত বিভ্রান্তিকর হচ্ছে।):
সংরক্ষণ ছাড়া 100 টি উপাদান মিশ্রিত inোকান

আমরা দেখতে পেলাম যে আদেশযুক্ত সন্নিবেশ, ফলাফল পিছনে চাপানো এবং অত্যন্ত দ্রুত extremely তবে, আমার বেঞ্চমার্কের অ-চার্টেড ফলাফল থেকে, আমি এটিও বলতে পারি যে এটি ব্যাক-সন্নিবেশের জন্য পরম অনুকূলতার কাছাকাছি নয়। 10 কে উপাদানগুলিতে, নিখুঁত ব্যাক-সন্নিবেশ অনুকূলতা একটি প্রাক-সংরক্ষিত ভেক্টরের উপর প্রাপ্ত হয়। যা আমাদের 3 মিলিয়ন চক্র দেয়; অর্ডার সন্নিবেশের জন্য আমরা এখানে 4.8M পর্যবেক্ষণ করি flat_map(অতএব সর্বোত্তমের 160%)।

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

3 টি উপাদানের এলোমেলো অনুসন্ধান (1 টির মধ্যে ঘড়ির পুনঃনির্ধারণ)

আকারে = 100

100 উপাদানের ধারক মধ্যে র্যান্ড অনুসন্ধান

আকারে = 10000

10000 উপাদানের ধারক মধ্যে র্যান্ড অনুসন্ধান

পুনরাবৃত্তির

100 এর বেশি আকারের (কেবলমাত্র মিডিয়ামপড টাইপ)

100 টিরও বেশি মাঝারি পোডকে ইট্রেটেশন করুন

ওপরের আকার 10000 (কেবলমাত্র মিডিয়ামপড টাইপ)

10000 টিরও বেশি মাঝারি পোডকে ইট্রেটেশন

লবণের চূড়ান্ত দানা

শেষ পর্যন্ত আমি "বেঞ্চমার্কিং P3 পিটি 1" (সিস্টেম বরাদ্দকারী) এ ফিরে আসতে চেয়েছিলাম। সাম্প্রতিক একটি পরীক্ষায় আমি যে ওপেন অ্যাড্রেস হ্যাশ ম্যাপটির বিকাশ করেছি তার কার্য সম্পাদন করছি, কিছু std::unordered_mapব্যবহারের ক্ষেত্রে উইন্ডোজ 7 এবং উইন্ডোজ 8 এর মধ্যে পারফরম্যান্সের ব্যবধান 3000% এর চেয়ে বেশি পরিমাপ করেছি ( এখানে আলোচনা করা হয়েছে )।
যা আমাকে উপরের ফলাফলগুলি সম্পর্কে পাঠককে সতর্ক করতে চায় (সেগুলি উইন 7-এ তৈরি হয়েছিল): আপনার মাইলেজটি ভিন্ন হতে পারে।

শুভেচ্ছান্তে


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

1
@ বিলিওনিল: আহ, আমরা সহকর্মীর সাথে কোডটি পরিদর্শন করেছি এবং অপরাধীটিকে পেয়েছি, আমার "এলোমেলো" সন্নিবেশটির আদেশ দেওয়া হয়েছিল কারণ Iোকানো কীগুলি অনন্য ছিল তা নিশ্চিত করার জন্য আমি একটি স্ট্যান্ড :: সেট ব্যবহার করেছি। এটি একটি স্পষ্ট দুর্বলতা, তবে আমি স্থির করে দিয়েছি যে এলোমেলো শ্যাফলের সাহায্যে আমি এখনই পুনর্নির্মাণ করছি এবং কিছু নতুন ফলাফল সম্পাদনা করার সাথে সাথে শীঘ্রই উপস্থিত হবে। সুতরাং তার বর্তমান অবস্থায় পরীক্ষাটি প্রমাণ করে যে "অর্ডার করা সন্নিবেশ" খুব তাড়াতাড়ি।
v.oddou

3
"ইন্টেলের একটি কাগজ আছে" here এবং এটি এখানে রয়েছে
isomorphismes

5
সম্ভবত আমি স্পষ্ট কিছু মিস করছি, তবে আমি কেন বুঝতে পারছি না কেন এলোমেলো অনুসন্ধানের flat_mapতুলনায় তুলনা কম std::map- কেউ কি এই ফলাফলটি ব্যাখ্যা করতে সক্ষম?
বালক

1
আমি এটিকে এই সময়ের বুস্ট বাস্তবায়নের নির্দিষ্ট ওভারহেড হিসাবে ব্যাখ্যা করব, এবং flat_mapধারক হিসাবে কোনও অভ্যন্তরীণ চরিত্র নয় । কারণ Aska::সংস্করণটি দেখার চেয়ে দ্রুত std::map। অপ্টিমাইজেশনের জন্য জায়গা রয়েছে তা প্রমাণ করে। প্রত্যাশিত পারফরম্যান্স অ্যাসিপটোটিক্যালি একই, তবে ক্যাশে লোকালটির জন্য সম্ভবত কিছুটা ভাল ধন্যবাদ। উচ্চ আকারের সেটগুলির সাথে তাদের একত্রিত হওয়া উচিত।
v.oddou

6

দস্তাবেজগুলি থেকে মনে হয় এটি সাদৃশ্যযুক্ত Loki::AssocVectorযার সাথে আমি মোটামুটি ভারী ব্যবহারকারী। যেহেতু এটি কোনও ভেক্টরের উপর ভিত্তি করে এটিতে একটি ভেক্টরের বৈশিষ্ট্য রয়েছে, এটি বলা যায়:

  • আইট্রেটাররা যখনই এর sizeবাইরে বেড়ে যায় তখন অবৈধ হয়ে যায় capacity
  • যখন এটি বৃদ্ধি পরলোক capacityএটা পুনরায় বরাদ্দ করা প্রয়োজন এবং নড়াচড়ায় তোমার ছিলো ঢোকাতে বিশেষ মামলায় ব্যতীত উপর বস্তু, অর্থাত সন্নিবেশ নিশ্চিত করা হয় না ধ্রুবক সময় endযখনcapacity > size
  • std::mapক্যাশে স্থানীয়তার কারণে লুকআপ দ্রুততর , একটি বাইনারি অনুসন্ধান যা std::mapঅন্যথায় হিসাবে একই কর্মক্ষমতা বৈশিষ্ট্য রয়েছে has
  • কম স্মৃতি ব্যবহার করে কারণ এটি কোনও লিঙ্কযুক্ত বাইনারি গাছ নয়
  • আপনি জোর করে এটিকে না বললে এটি কখনই সঙ্কুচিত হয় না (যেহেতু এটি পুনঃস্থাপনের সূচনা করে)

সর্বোত্তম ব্যবহার হ'ল আপনি যখন reserveআগুনের উপাদানগুলির সংখ্যা জানেন (যাতে আপনি সম্মুখভাগে আসতে পারেন ), বা সন্নিবেশ / অপসারণ বিরল হয় তবে তাত্পর্যটি ঘন ঘন হয়। আইট্রেটার অবৈধকরণ কিছু ব্যবহারের ক্ষেত্রে এটি কিছুটা জটিল করে তোলে যাতে তারা প্রোগ্রামের যথার্থতার ক্ষেত্রে পদ পরিবর্তন করতে না পারে।


1
মিথ্যা :) উপরের পরিমাপগুলি অপারেশনের সন্ধানের জন্য ফ্ল্যাট_ম্যাপের চেয়ে দ্রুততর মানচিত্র দেখায়, আমি অনুমান করি যে পিপিএল বাস্তবায়ন ঠিক করা দরকার, তবে তত্ত্ব অনুসারে আপনি সঠিক।
NoSenseEtAl
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.