এমএমএপি () বনাম পড়ার ব্লক


184

আমি এমন একটি প্রোগ্রামে কাজ করছি যা সম্ভাব্য 100 গিগাবাইট বা তার বেশি আকারের ফাইল হতে পারে processing ফাইলগুলিতে পরিবর্তনশীল দৈর্ঘ্যের রেকর্ডগুলির সেট রয়েছে। আমি একটি প্রথম বাস্তবায়ন পেয়েছি এবং চলছে এবং এখন ইনপুট ফাইলটি বেশ কয়েকবার স্ক্যান হওয়ার পরে, বিশেষত I / O আরও দক্ষতার সাথে করাতে পারফরম্যান্সের উন্নতির দিকে তাকিয়ে আছি।

mmap()সি ++ এর fstreamলাইব্রেরির মাধ্যমে ব্লকগুলিতে পড়া বনাম ব্যবহারের জন্য কি কোনও থাম্বের নিয়ম রয়েছে ? আমি যা করতে চাই তা হ'ল ডিস্ক থেকে বাফারে বড় ব্লকগুলি পড়া, বাফার থেকে সম্পূর্ণ রেকর্ড প্রক্রিয়া করা এবং তারপরে আরও পড়ুন।

mmap()কোড সম্ভাব্য খুব যেহেতু অগোছালো পেতে পারে mmap; 'd ব্লক মিথ্যা প্রয়োজন পৃষ্ঠার গণ্ডি (আমার বোঝার) মাপের এবং রেকর্ড পারা সম্ভাব্য জুড়ে মত পৃষ্ঠা গণ্ডি। সঙ্গে fstreamগুলি, আমি শুধু একটি রেকর্ড শুরুর করার চেষ্টা এবং যেহেতু আমরা ব্লক পড়া ঐ পৃষ্ঠাতে মিথ্যা মাপের গণ্ডি সীমাবদ্ধ নয় করছি, আবার পড়া শুরু করতে পারবেন।

আমি প্রথমে সম্পূর্ণ বাস্তবায়ন না লিখে এই দুটি বিকল্পের মধ্যে কীভাবে সিদ্ধান্ত নেব? থাম্বের কোনও নিয়ম (উদাহরণস্বরূপ, mmap()2x দ্রুত) বা সাধারণ পরীক্ষা?


1
এটি একটি আকর্ষণীয় পঠনযোগ্য: মাঝারি . com / @sasha_f/… পরীক্ষায় সিস্কলmmap() ব্যবহারের চেয়ে 2-6 গুণ বেশি দ্রুত হয়, যেমন read()
এমপ্ল্যাটনার

উত্তর:


208

আমি লিনাক্সে এমএমএপ / পড়ার পারফরম্যান্সের চূড়ান্ত শব্দটি সন্ধান করার চেষ্টা করছিলাম এবং আমি লিনাক্স কার্নেল মেলিং তালিকার একটি দুর্দান্ত পোস্ট ( লিঙ্ক ) পেয়েছি । এটা তোলে 2000 থেকে, তাই সেখানে আই এবং তারপর থেকে কার্নেল ভার্চুয়াল মেমরি অনেক উন্নতি হয়েছে, কিন্তু এটা চমত্কারভাবে কারণে ব্যাখ্যা করে mmapবা readদ্রুত বা মন্থর হতে পারে।

  • একটি কলের mmapচেয়ে বেশি ওভারহেড রয়েছে read(যেমন epollতার চেয়ে বেশি ওভারহেড থাকে poll, যার চেয়ে বেশি ওভারহেড থাকে read)। ভার্চুয়াল মেমরি ম্যাপিংস পরিবর্তন করা কিছু প্রসেসরের একই কারণে বিভিন্ন প্রসেসের মধ্যে স্যুইচিং ব্যয়বহুল একটি ব্যয়বহুল ক্রিয়াকলাপ।
  • আইও সিস্টেমটি ইতিমধ্যে ডিস্ক ক্যাশে ব্যবহার করতে পারে, সুতরাং আপনি যদি কোনও ফাইল পড়ে থাকেন তবে আপনি ক্যাশেটি হিট করবেন বা আপনি কোনও পদ্ধতি ব্যবহার না করে তা মিস করবেন।

যাহোক,

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

এমএমএপ / পড়ার আলোচনা আমাকে আরও দুটি পারফরম্যান্স আলোচনার স্মরণ করিয়ে দেয়:

  • কিছু জাভা প্রোগ্রামাররা অবাক হয়ে জানতে পেরেছিলেন যে ননব্লকিং I / O প্রায়শই I / O- কে ব্লক করার চেয়ে ধীর হয়, আপনি যদি জানেন যে ননব্লকিং I / O এর জন্য আরও বেশি সিস্টেম তৈরি করা দরকার।

  • কিছু অন্যান্য নেটওয়ার্ক প্রোগ্রামার শিখতে হতবাক হয়েছিল epollযা প্রায়শই ধীর হয় poll, যা আপনি যদি জানেন যে ম্যানেজিংয়ের epollজন্য আরও বেশি সিস্টেম তৈরি করা প্রয়োজন।

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

(এই প্রশ্নটি নেক্রো করার জন্য দুঃখিত, তবে আমি একটি উত্তর খুঁজছিলাম এবং এই প্রশ্নটি গুগলের ফলাফলের শীর্ষে আসতে থাকবে))


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

আপশটটি হ'ল, আমার (আধুনিক ইন্টেল, সার্কা 2018) হার্ডওয়্যারটিতে, পৃষ্ঠার চেয়ে বড় আকারের (4 কিবি) পড়ার mmapচেয়ে ওভারহেড কম রয়েছে read। এখন এটি খুব সত্য যে আপনি যদি অল্প পরিমাণে এবং এলোমেলোভাবে ডেটা অ্যাক্সেস করতে চান তবে সত্যই সত্য mmap- তবে কনভার্সটি সত্য নয়: mmapতবুও ধারাবাহিক অ্যাক্সেসের জন্য সেরা হতে পারে।
BeeOnRope

1
@ বিঅনরোপ: আপনি 2000 এর দশকের হার্ডওয়্যার এবং সফ্টওয়্যার ভিত্তিতে পরামর্শের বিষয়ে সন্দেহবাদী হতে পারেন তবে আমি এমন মানদণ্ড সম্পর্কে আরও সন্দেহবাদী যেগুলি কোনও পদ্ধতি এবং ডেটা সরবরাহ করে না। আপনি যদি একটি কেস mmapদ্রুততর করতে চান তবে আমি আশা করতে পারি যে সারণিযুক্ত ফলাফলগুলি সহ কম পরীক্ষার সম্পূর্ণ উত্স (উত্স কোড) এবং প্রসেসরের মডেল নম্বরটি দেখতে পাব bare
ডায়েটারিচ এপ্পে

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

2
@ ডায়েটরিচএপ - হ্যাঁ, আমি টিএলবি এর প্রভাবগুলিতে ভাল পারদর্শী। নোট করুন যে mmapঅস্বাভাবিক পরিস্থিতিতে (তবে munmapসম্ভবত) ব্যতীত টিএলবি ফ্লাশ করে না । আমার পরীক্ষাগুলিতে উভয়ই মাইক্রোবেনমার্কসকে অন্তর্ভুক্ত করে (সহ munmap) এবং বাস্তব প্রয়োগের ক্ষেত্রে চলমান "প্রয়োগে" " অবশ্যই আমার অ্যাপ্লিকেশনটি আপনার অ্যাপ্লিকেশনটির মতো নয়, তাই লোকালদের স্থানীয়ভাবে পরীক্ষা করা উচিত। এটি কোনও স্পষ্টও নয় যে mmapএকটি মাইক্রো-বেঞ্চমার্কের read()পক্ষেও রয়েছে : এটির ফলে ব্যবহারকারী-পক্ষের গন্তব্য বাফার সাধারণত এল 1 এ থাকে, এটি বৃহত্তর প্রয়োগে নাও ঘটে। হ্যাঁ, "এটি জটিল"।
BeeOnRope

47

প্রধান পারফরম্যান্স ব্যয়টি ডিস্ক i / o হতে চলেছে। "এমএমএপ ()" অবশ্যই আইট্রিমের চেয়ে দ্রুত, তবে পার্থক্যটি লক্ষণীয় নয় কারণ ডিস্ক i / o আপনার রান-টাইমে প্রভাব ফেলবে।

"এমএমএপ () উপায় দ্রুত" এবং তার পরিমাপযোগ্য কোনও পার্থক্য খুঁজে পাওয়া যায়নি বলে তার দৃ test় প্রতিবেদনের জন্য আমি বেন কলিন্সের কোড টুকরা (উপরে / নীচে দেখুন) চেষ্টা করেছি tried তার উত্তর সম্পর্কে আমার মন্তব্য দেখুন।

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

আপনার ক্ষেত্রে আমি মনে করি এমএমএপ (), ইসট্রিম এবং নিম্ন-স্তরের ওপেন () / রিড () কলগুলি একই রকম হবে। আমি এই ক্ষেত্রে এমএমএপি () সুপারিশ করব:

  1. এবং ফাইলের মধ্যে এলোমেলো অ্যাক্সেস (ক্রমযুক্ত নয়) রয়েছে AND
  2. পুরো জিনিসটি স্বাচ্ছন্দ্যে মেমরির সাথে ফিট করে বা ফাইলের মধ্যে স্থানীয়তার সাথে উল্লেখ রয়েছে যাতে নির্দিষ্ট পৃষ্ঠাগুলি ম্যাপ করা যায় এবং অন্যান্য পৃষ্ঠাগুলি ম্যাপ করা যায় out এই পদ্ধতিতে অপারেটিং সিস্টেমটি সর্বোচ্চ উপকারের জন্য উপলভ্য র‌্যাম ব্যবহার করে uses
  3. বা যদি একই ফাইলটিতে একাধিক প্রক্রিয়াগুলি পড়া / কাজ করছে তবে এমএমএপ () চমত্কার কারণ প্রক্রিয়াগুলি সমস্ত একই শারীরিক পৃষ্ঠাগুলি ভাগ করে।

(বিটিডব্লিউ - আমি এমএমএপ () / ম্যাপভিউঅফফাইলে () পছন্দ করি।


এলোমেলো অ্যাক্সেস সম্পর্কে ভাল পয়েন্ট: এটি আমার ধারণাকে চালিত করতে পারে be
বেন কলিন্স

1
আমি বলব না যে ফাইলটি কেবল আধার জায়গাতে মেমরির মধ্যে আরামে ফিট করে। সুতরাং 64 বিট সিস্টেমে বিশাল ফাইলগুলি ম্যাপ করার কোনও কারণ নেই। ওএস জানে যে কীভাবে পরিচালনা করতে হয়; এটি অদলবদলের জন্য একই যুক্তিযুক্ত তবে এই ক্ষেত্রে ডিস্কে অতিরিক্ত অদলবদলের প্রয়োজন হয় না।
এমভিজি 21

@ এমভিজি: আপনি কি ডিস্ক আই / ও এর পয়েন্টটি বুঝতে পারছেন? যদি ফাইলটি ঠিকানার জায়গাতে ফিট হয় তবে মেমোরি নয় এবং আপনার এলোমেলো অ্যাক্সেস থাকে তবে আপনার কাছে প্রতিটি রেকর্ড অ্যাক্সেস থাকতে পারে যা ডিস্কের হেড মুভ এবং সিক্স বা এসএসডি পৃষ্ঠার অপারেশন প্রয়োজন, যা কার্য সম্পাদনের জন্য একটি বিপর্যয়।
টিম কুপার 21

3
ডিস্ক i / o দিক অ্যাক্সেস পদ্ধতি থেকে স্বতন্ত্র হওয়া উচিত। আপনার যদি সত্যিকারের চেয়ে বড়-র‌্যাম ফাইলগুলিতে র্যান্ডম অ্যাক্সেস থাকে তবে এমএমএপ এবং সন্ধান করা + পঠন উভয়ই তীব্রভাবে ডিস্ক-আবদ্ধ। অন্যথায় উভয়ই ক্যাশে থেকে উপকৃত হবে। আমি মেমরির আকারের সাথে তুলনা করে ফাইলের আকারটিকে উভয় দিকের শক্ত যুক্তি হিসাবে দেখছি না। অন্যদিকে ফাইলের আকার বনাম অ্যাড্রেস স্পেস একটি খুব দৃ argument় যুক্তি, বিশেষত সত্যিকারের এলোমেলো অ্যাক্সেসের জন্য।
এমভিজি

আমার আসল উত্তরের এই পয়েন্টটি ছিল এবং রয়েছে: "পুরো জিনিসটি স্মৃতিতে স্বাচ্ছন্দ্যে ফিট করে অথবা ফাইলের মধ্যে লোকাল-অফ-রেফারেন্স থাকে"। সুতরাং 2 য় পয়েন্ট আপনি যা বলছেন তা সম্বোধন করে।
টিম কুপার

43

এমএমএপ উপায় দ্রুত। নিজের কাছে এটি প্রমাণ করার জন্য আপনি একটি সাধারণ বেঞ্চমার্ক লিখতে পারেন:

char data[0x1000];
std::ifstream in("file.bin");

while (in)
{
  in.read(data, 0x1000);
  // do something with data
}

বনাম:

const int file_size=something;
const int page_size=0x1000;
int off=0;
void *data;

int fd = open("filename.bin", O_RDONLY);

while (off < file_size)
{
  data = mmap(NULL, page_size, PROT_READ, 0, fd, off);
  // do stuff with data
  munmap(data, page_size);
  off += page_size;
}

স্পষ্টতই, আমি বিশদটি রেখে যাচ্ছি ( page_sizeউদাহরণস্বরূপ, আপনার ফাইলটি একাধিক নয় এমন ইভেন্টে আপনি যখন ফাইলের শেষের দিকে পৌঁছবেন তখন কীভাবে তা নির্ধারণ করবেন) তবে এটি এর চেয়ে বেশি জটিল হওয়া উচিত নয় should ।

যদি আপনি এটি করতে পারেন তবে আপনি আপনার ডেটা একাধিক ফাইলের মধ্যে বিভক্ত করার চেষ্টা করতে পারেন যা এমএমএপ () হতে পারে - অংশের পরিবর্তে পুরো সম্পাদনা (অনেক সহজ)।

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

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

চূড়ান্ত আপডেট : দেখুন, লোকেরা: ওএস এবং স্ট্যান্ডার্ড লাইব্রেরি এবং ডিস্ক এবং মেমরি শ্রেণিবদ্ধের বিভিন্ন প্ল্যাটফর্মের সংমিশ্রণে আমি নিশ্চিতভাবে বলতে পারি না যে mmapব্ল্যাক বক্স হিসাবে দেখা সিস্টেম কলটি সর্বদা সর্বদা যথেষ্ট দ্রুত থাকবে চেয়ে read। এটি আমার উদ্দেশ্যটি ঠিক ছিল না, এমনকি যদি আমার শব্দগুলি সেভাবে বোঝানো যায়। শেষ পর্যন্ত, আমার বক্তব্যটি ছিল যে মেমরি-ম্যাপ করা i / o সাধারণত বাইট-ভিত্তিক i / o এর চেয়ে দ্রুত হয়; এটি এখনও সত্য । আপনি যদি পরীক্ষামূলকভাবে খুঁজে পান যে দুজনের মধ্যে কোনও পার্থক্য নেই, তবে কেবলমাত্র আমার কাছে যুক্তিযুক্ত বলে মনে হচ্ছে আপনার প্ল্যাটফর্মটি কলের আওতায় মেমরি-ম্যাপিং এমনভাবে প্রয়োগ করে যাতে কলগুলি সম্পাদন করার পক্ষে সুবিধাজনক হয় inread। আপনি পোর্টেবল উপায়ে মেমরি-ম্যাপযুক্ত i / o ব্যবহার করছেন তা একমাত্র নিশ্চিত হওয়ার একমাত্র উপায় mmap। আপনি যদি বহনযোগ্যতার বিষয়ে চিন্তা করেন না এবং আপনি আপনার লক্ষ্য প্ল্যাটফর্মগুলির নির্দিষ্ট বৈশিষ্ট্যগুলির উপর নির্ভর করতে পারেন, তবে readকোনওরকম পারফরম্যান্স ত্যাগ ছাড়াই ব্যবহার করা উপযুক্ত হতে পারে।

উত্তর তালিকা পরিষ্কার করতে সম্পাদনা করুন: @ জেবিএল:

স্লাইডিং উইন্ডো এমএমএপি আকর্ষণীয় মনে হচ্ছে। আপনি এই সম্পর্কে আরও কিছু বলতে পারেন?

অবশ্যই - আমি গিটের জন্য একটি সি ++ গ্রন্থাগার লিখছিলাম (একটি লিবিগিট ++, আপনি যদি করেন) তবে আমি এটির মতোই একটি সমস্যায় পড়েছিলাম: আমার বড় (খুব বড়) ফাইলগুলি খুলতে সক্ষম হতে হবে এবং মোট কুকুরের পারফরম্যান্স নেই (এটি যেমন হবে std::fstream)

Boost::Iostreamsইতিমধ্যে একটি ম্যাপযুক্ত mmapফাইল ফাইল রয়েছে তবে সমস্যাটি হ'ল এটি পুরো ফাইলগুলিকে পিং করছিল যা আপনাকে 2 ^ (ওয়ার্ডাইজ) হিসাবে সীমাবদ্ধ করে। 32-বিট মেশিনে, 4 জিবি যথেষ্ট বড় নয়। .packগিটে যে ফাইলগুলি তার চেয়ে অনেক বড় হয়ে উঠেছে এটি আশা করা অযৌক্তিক নয় , তাই নিয়মিত ফাইল i / o এর অবলম্বন না করেই খণ্ডগুলিতে ফাইলটি পড়া দরকার ছিল। এর প্রচ্ছদের অধীনে Boost::Iostreams, আমি একটি উত্স প্রয়োগ করেছি, যা কমবেশি std::streambufএবং এর মধ্যে মিথস্ক্রিয়াটির অন্য একটি দৃষ্টিভঙ্গি std::istream। এছাড়াও আপনি শুধু inheriting দ্বারা একটি অনুরূপ পদ্ধতির চেষ্টা করে দেখতে পারেন std::filebufএকটি মধ্যে mapped_filebufএবং একইভাবে, inheriting std::fstreamমধ্যে a mapped_fstream। এটি সঠিকভাবে পাওয়া দু'জনের মধ্যে মিথস্ক্রিয়া। Boost::Iostreams আপনার জন্য কিছু কাজ করেছে, এবং এটি ফিল্টার এবং চেইনের জন্য হুক সরবরাহ করে, তাই আমি ভেবেছিলাম যে এটি সেভাবে বাস্তবায়ন করা আরও কার্যকর হবে।


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

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

3
@ টিম কুপার: আপনি এই থ্রেডটি খুঁজে পেতে পারেন ( মার্কমেইল.আর / ম্যাসেজ / )) of দুটি জিনিস নোট করুন: এমএমএপ লিনাক্সে সঠিকভাবে অনুকূলিত হয় না, এবং সর্বোত্তম ফলাফল পেতে তাদের পরীক্ষায় ম্যাডভিস ব্যবহার করা প্রয়োজন।
বেন কলিন্স

9
প্রিয় বেন: আমি সেই লিঙ্কটি পড়েছি। যদি লিনাক্সে 'এমএমএপ ()' দ্রুত না হয় এবং ম্যাপভিউঅফফাইলে () উইন্ডোজটিতে দ্রুত না হয়, তবে আপনি কি দাবি করতে পারেন যে "এমএমএপটি দ্রুততর হয়?" এছাড়াও, তাত্ত্বিক কারণে আমি বিশ্বাস করি এমএমএপ () ক্রমযুক্ত পাঠের জন্য দ্রুত নয় - আপনার বিপরীতে কোনও ব্যাখ্যা আছে কি?
টিম কুপার

11
বেন, কেন mmap()ফাইলগুলি একবারে কোনও পৃষ্ঠাতে বিরক্ত করবেন ? যদি কোনও size_tফাইলের আকার (likely৪-বিট সিস্টেমে খুব সম্ভবত) ধরে রাখতে যথেষ্ট পরিমাণে থাকে, তবে কেবলমাত্র mmap()একটি কলেই পুরো ফাইলটি।
স্টিভ এমারসন

39

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

এমএমএপি ম্যাজিক মত মনে হচ্ছে

ফাইলটি ইতিমধ্যে 1 কে বেসলাইন 2 হিসাবে সম্পূর্ণরূপে ক্যাশে করা হয়েছে এমন কেসটি গ্রহণ করা , mmapসম্ভবত ম্যাজিকের মতো দেখতে বেশ সম্ভবত :

  1. mmap পুরো ফাইলটি ম্যাপ করতে কেবলমাত্র 1 টি কম্পিউটার কল প্রয়োজন (সম্ভাব্য) ম্যাপ, এর পরে আর কোনও সিস্টেম কল প্রয়োজন হয় না।
  2. mmap কার্নেল থেকে ব্যবহারকারী-স্পেসে ফাইলের একটি অনুলিপি প্রয়োজন হয় না।
  3. mmapসংকলক স্বয়ং-ভেক্টরাইজেশন, সিমডি ইন্টারসিনিক্স, প্রিফেচিং, মেমরি পার্সিং রুটিনগুলি, ওপেনএমপি ইত্যাদির মতো যেকোনো উন্নত কৌশল দ্বারা এটি প্রক্রিয়াকরণ সহ আপনাকে "মেমরি হিসাবে" ফাইলটি অ্যাক্সেস করার অনুমতি দেয় including

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

ভাল, এটা করতে পারেন।

এমএমএপ আসলে যাদু নয় কারণ ...

এমএমএপ এখনও প্রতি পৃষ্ঠার কাজ করে

একটি প্রাথমিক লুকানো খরচ mmapবনাম read(2)(যা সত্যিই তুলনীয় অপারেটিং সিস্টেম-স্তরীয় প্রাপ্ত syscall হয় ব্লক পড়া ) সঙ্গে যে mmapআপনি ব্যবহারকারীর-স্পেস প্রতিটি 4K পৃষ্ঠার জন্য "কিছু কাজ" করতে যদিও এটি দ্বারা লুকানো করা যেতে পারে প্রয়োজন হবে, পৃষ্ঠা-ফল্ট প্রক্রিয়া

উদাহরণস্বরূপ একটি সাধারণ প্রয়োগ যা কেবলমাত্র mmapপুরো ফাইলটির জন্য একটি 100 জিবি ফাইল পড়তে 100 জিবি / 4 কে = 25 মিলিয়ন ত্রুটি করতে হবে fault এখন, এগুলি ছোটখাটো ত্রুটিযুক্ত হবে , তবে 25 বিলিয়ন পৃষ্ঠার ত্রুটিগুলি এখনও খুব দ্রুত গতিতে চলেছে না। একটি ছোটখাটো ত্রুটির ব্যয় সম্ভবত সেরা ক্ষেত্রে 100 এর দশকের ন্যানোর মধ্যে।

এমএএমএপ টিএলবির পারফরম্যান্সের উপর নির্ভর করে

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

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

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

পড়ুন () এই সমস্যাগুলি এড়ায়

read()প্রাপ্ত syscall, যা কি সাধারণত ভিত্তি "ব্লক পড়া" টাইপ কল সি, সি ++ মধ্যে যেমন প্রদত্ত এবং অন্যান্য ভাষায় এক প্রাথমিক অসুবিধা আছে যা সবার ভালোভাবেই অবগত হল:

  • read()এন বাইটের প্রতিটি কল অবশ্যই কার্নেল থেকে ব্যবহারকারী স্পেসে এন বাইট অনুলিপি করতে হবে।

অন্যদিকে, এটি উপরের বেশিরভাগ ব্যয় এড়িয়ে চলে - আপনার 25 মিলিয়ন 4K পৃষ্ঠাগুলিতে ব্যবহারকারীর জায়গায় ম্যাপ করার দরকার নেই। আপনি mallocব্যবহারকারীর স্পেসে সাধারণত একটি একক বাফার ছোট বাফার করতে পারেন এবং আপনার সমস্ত readকলের জন্য বারবার ব্যবহার করতে পারেন । কার্নেলের পাশে, 4K পৃষ্ঠাগুলি বা টিএলবি মিস করা প্রায় কোনও সমস্যা নেই কারণ সমস্ত র‌্যাম সাধারণত কয়েকটি খুব বড় পৃষ্ঠাগুলি (যেমন, x86 এ 1 জিবি পৃষ্ঠাগুলি) ব্যবহার করে রৈখিকভাবে ম্যাপ করা হয়, সুতরাং পৃষ্ঠার ক্যাশে অন্তর্নিহিত পৃষ্ঠাগুলি areাকা থাকে কার্নেল স্পেসে খুব দক্ষতার সাথে।

সুতরাং মূলত কোনও বড় ফাইলের একক পঠনের জন্য কোনটি দ্রুত তা নির্ধারণ করার জন্য আপনার নীচের তুলনাটি রয়েছে:

mmapকার্নেল থেকে ব্যবহারকারীর জায়গায় ফাইলের বিষয়বস্তু অনুলিপি করার প্রতি-বাইট কাজের চেয়ে অতিরিক্ত প্রতি পৃষ্ঠার কাজটি কী পদ্ধতির দ্বারা নিহিত read()?

অনেক সিস্টেমে এগুলি আসলে প্রায় ভারসাম্যপূর্ণ। মনে রাখবেন যে হার্ডওয়্যার এবং ওএস স্ট্যাকের সম্পূর্ণ আলাদা বৈশিষ্ট্যযুক্ত প্রতিটি স্কেল করে।

বিশেষত, mmapপদ্ধতির তুলনামূলকভাবে দ্রুত হয় যখন:

  • ওএসের দ্রুত গৌণ-ত্রুটি পরিচালনা এবং বিশেষত ছোট্ট-ত্রুটিযুক্ত বাল্ক অপ্টিমাইজেশান যেমন ফল্ট-এ্যভার্ড রয়েছে।
  • ওএসের একটি MAP_POPULATEকার্যকর বাস্তবায়ন রয়েছে যা উদাহরণস্বরূপ, অন্তর্নিহিত পৃষ্ঠাগুলি শারীরিক স্মৃতিতে সামঞ্জস্যপূর্ণ ক্ষেত্রে বড় ম্যাপগুলিকে দক্ষতার সাথে প্রক্রিয়া করতে পারে।
  • হার্ডওয়ারটিতে পৃষ্ঠার অনুবাদ সম্পাদন শক্তিশালী রয়েছে যেমন বড় টিএলবি, দ্রুত দ্বিতীয় স্তরের টিএলবি, দ্রুত এবং সমান্তরাল পৃষ্ঠা-ওয়াকার্স, অনুবাদ সহ ভাল প্রিফেচ ইন্টারঅ্যাকশন ইত্যাদি।

... যখন read()পদ্ধতির তুলনামূলকভাবে দ্রুত হয় যখন:

  • read()প্রাপ্ত syscall ভাল কপি কর্মক্ষমতা আছে। উদাহরণস্বরূপ, copy_to_userকার্নেল দিকে ভাল পারফরম্যান্স।
  • কার্নেলের মেমরি ম্যাপ করার জন্য একটি কার্যকর (ব্যবহারকারীর সাথে তুলনামূলক) উপায় রয়েছে, যেমন, হার্ডওয়্যার সমর্থন সহ কয়েকটি বড় পৃষ্ঠা ব্যবহার করা।
  • কার্নেলের দ্রুত সিস্কল রয়েছে এবং সিস্টেল জুড়ে কার্নেল টিএলবি এন্ট্রি রাখার একটি উপায় রয়েছে।

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

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

  • উপরে বর্ণিত দোষের চারপাশের সংযোজন, যা কেসটিকে সত্যই mmapছাড়াই সহায়তা করে MAP_POPULATE
  • দ্রুতগতির copy_to_userপদ্ধতিগুলির সংযোজন arch/x86/lib/copy_user_64.S, উদাহরণস্বরূপ, REP MOVQযখন দ্রুত হয় তখন ব্যবহার করা যা প্রকৃত পক্ষে কেসকে সহায়তা করে read()

স্পেক্টর এবং মেল্টডাউন পরে আপডেট

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

read()ভিত্তিক পদ্ধতির তুলনায় এগুলি সমস্ত ভিত্তিক পদ্ধতির তুলনামূলক অসুবিধা mmap, কারণ read()পদ্ধতিগুলি অবশ্যই প্রতিটি "বাফার আকার" মূল্যবান ডেটার জন্য একটি সিস্টেম কল করতে হবে। আপনি এই ব্যয়টি নির্বিঘ্ন করতে ইচ্ছামত বাফার আকারটি বাড়িয়ে তুলতে পারবেন না যেহেতু বড় বাফারগুলি সাধারণত L1 আকারের চেয়ে বেশি হয়ে থাকে এবং তাই আপনি ক্রমাগত ক্যাশে মিস করে যাচ্ছেন সেহেতু বড় বাফারগুলি ব্যবহার করা খারাপ হয়।

অন্যদিকে, এর সাহায্যে mmapআপনি MAP_POPULATEকেবলমাত্র একটি একক সিস্টেম কল ব্যয়ে মেমরির একটি বৃহত অঞ্চলে ম্যাপিং করতে এবং দক্ষতার সাথে অ্যাক্সেস করতে পারেন।


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

2 ... কারণ যদি ফাইলটি ক্যাশে না করা হয় তবে আপনার আচরণটি আইও উদ্বেগের সাথে সম্পূর্ণরূপে আধিপত্য বয়ে চলেছে, সহ অন্তর্নিহিত হার্ডওয়্যারের সাথে আপনার অ্যাক্সেস প্যাটার্নটি কতটা সহানুভূতিশীল রয়েছে - এবং আপনার সমস্ত প্রচেষ্টা যেমন অ্যাক্সেস নিশ্চিত করতে হবে ততই সহানুভূতিশীল সম্ভব, উদাহরণস্বরূপ madviseবা fadviseকল ব্যবহারের মাধ্যমে (এবং অ্যাক্সেস প্যাটার্নগুলি উন্নত করতে আপনি যে কোনও অ্যাপ্লিকেশন স্তরের পরিবর্তন করতে পারেন)

3 আপনি এটির কাছাকাছি যেতে পারেন, উদাহরণস্বরূপ, mmapছোট আকারের উইন্ডোগুলিতে ধারাবাহিকভাবে ইনপুট করে 100 এমবি বলুন।

4 প্রকৃতপক্ষে, এটিটিMAP_POPULATE প্রমাণ করে যে (কমপক্ষে একটি হার্ডওয়ার / ওএসের সংমিশ্রণটি) এটি ব্যবহার না করার চেয়ে কিছুটা দ্রুত, সম্ভবত কার্নেলটি ফল্টআরন্ড ব্যবহার করছে - সুতরাং ছোটখাট ত্রুটির প্রকৃত সংখ্যা 16 এর ফ্যাক্টর দ্বারা হ্রাস পেয়েছে অথবা তাই.


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

5
হ্যাঁ, এটি অনেকটা দৃশ্যের উপর নির্ভর করে। আপনি যদি পড়েন যথেষ্ট ছোট এবং সময়ের সাথে সাথে আপনি বার বার একই বাইটগুলি পড়তে চান তবে এটি mmapএকটি দুর্গম সুবিধা পাবে কারণ এটি স্থির কার্নেল কল ওভারহেড এড়িয়ে চলে। অন্যদিকে, mmapটিএলবি চাপও বৃদ্ধি করে এবং "ওয়ার্ম আপ" পর্বের জন্য ধীরে ধীরে তৈরি করুন যেখানে বর্তমান প্রক্রিয়াতে প্রথমবারের জন্য বাইটগুলি পড়া হচ্ছে (যদিও তারা এখনও পৃষ্ঠা পৃষ্ঠায় রয়েছে), যেহেতু এটি হতে পারে এর চেয়ে আরও বেশি কাজ read, উদাহরণস্বরূপ "ফল্ট-এ্যুয়ার্ড" সংলগ্ন পৃষ্ঠাগুলি ... এবং একই অ্যাপ্লিকেশনগুলির জন্য "ওয়ার্ম আপ" এগুলি গুরুত্বপূর্ণ! @ কেটানোসৌয়ার
BeeOnRope

আমি মনে করি আপনি যেখানে বলেছেন "... তবে 25 বিলিয়ন পৃষ্ঠার ত্রুটিগুলি এখনও খুব দ্রুত হবে না ..." এটি পড়তে হবে "... তবে 25 মিলিয়ন পৃষ্ঠার ত্রুটিগুলি এখনও সুপার দ্রুত হবে না ..." । আমি 100% ধনাত্মক নই, সে কারণেই আমি সরাসরি সম্পাদনা করছি না।
টন ভ্যান ডেন হিউভেল

7

আমি দুঃখিত, বেন কলিন্স তার স্লাইডিং উইন্ডোজ এমএমএপ উত্স কোডটি হারিয়েছেন। বুস্ট এ পেয়ে ভালো লাগবে।

হ্যাঁ, ফাইল ম্যাপিং অনেক দ্রুত। আপনি মেমরি-টু-ডিস্ক সংযুক্ত করতে ওএস বিপরীতে ওএস ভার্চুয়াল মেমরি সাবসিস্টেমটি মূলত ব্যবহার করছেন। এটি এইভাবে চিন্তা করুন: ওএস কার্নেল বিকাশকারীরা যদি এটি দ্রুত তৈরি করতে পারত। কারণ এটি করার ফলে প্রায় সমস্ত কিছুই দ্রুত হয়: ডাটাবেস, বুট টাইম, প্রোগ্রামের লোড টাইম, ইত্যাদি te

স্লাইডিং উইন্ডো অ্যাপ্রোচ সত্যিই এতটা কঠিন নয় যেহেতু একাধিক সংশ্লেষপূর্ণ পৃষ্ঠাগুলি একবারে ম্যাপ করা যায়। সুতরাং যে কোনও একক রেকর্ডের বৃহত্তম মেমরির মধ্যে মাপসই করা হবে তাই রেকর্ডের আকারটি এতক্ষণ গুরুত্ব দেয় না। গুরুত্বপূর্ণ বিষয় হ'ল বইয়ের রক্ষণাবেক্ষণ করা।

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

উইন্ডোজ এর অধীনে ক্রিয়েটফাইলম্যাপিং () এবং ম্যাপভিউওফাইফিল () এবং সিএসটিএমএনপিএফ.ডুএলোকেশনগ্রাণালিটি পেতে SYSTEM_INFO.dwPageSize নয়) ব্যবহার করে উইন্ডোজের অধীনে এই সমস্ত কিছু ঠিক আছে।


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

4

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

এটি বলার পরে, পারফরম্যান্সের উন্নতির জন্য আরও ভাল উপায় হতে পারে। আপনি বলেছিলেন যে ইনপুট ফাইলটি অনেকবার স্ক্যান হয়ে যায় , আপনি যদি একটি পাসে এটি পড়তে পারেন এবং তারপরে এটি সম্পন্ন করেন তবে এটি সম্ভবত আরও দ্রুত হতে পারে।


3

সম্ভবত আপনার ফাইলগুলি প্রাক-প্রক্রিয়া করা উচিত, সুতরাং প্রতিটি রেকর্ড পৃথক ফাইলে থাকে (বা কমপক্ষে প্রতিটি ফাইল একটি এমএমএপ-সক্ষম আকার)।

এছাড়াও আপনি প্রতিটি রেকর্ডের জন্য প্রসেসিংয়ের সমস্ত পদক্ষেপগুলি পরবর্তী কোনওটিতে যাওয়ার আগে করতে পারেন? সম্ভবত এটি আইও ওভারহেডের কিছু এড়াতে পারে?


3

আমি সম্মত হচ্ছি যে এমএমএপ করা ফাইল আই / ও দ্রুত হতে চলেছে, তবে কোডটি আপনার বেঞ্চমার্ক করার সময়, কাউন্টার উদাহরণটি কিছুটা অপ্টিমাইজ করা উচিত নয় ?

বেন কলিন্স লিখেছেন:

char data[0x1000];
std::ifstream in("file.bin");

while (in)
{
    in.read(data, 0x1000);
    // do something with data 
}

আমি চেষ্টা করার পরামর্শ দিচ্ছি:

char data[0x1000];
std::ifstream iifle( "file.bin");
std::istream  in( ifile.rdbuf() );

while( in )
{
    in.read( data, 0x1000);
    // do something with data
}

এবং এর বাইরে, আপনি বাফার আকারটিকে ভার্চুয়াল মেমরির এক পৃষ্ঠার মতো একই আকারেও চেষ্টা করতে পারেন, যদি 0x1000 আপনার মেশিনে ভার্চুয়াল মেমরির এক পৃষ্ঠার আকার না হয় ... আইএমএইচও এমএমপ ফাইল আই / ও এখনও আছে জিততে পারে, তবে এটি জিনিসগুলিকে আরও ঘনিষ্ঠ করে তুলবে।


2

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


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

2

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


এটি দুর্যোগের জন্য একটি রেসিপি মত শোনাচ্ছে। অবজেক্টের বিন্যাস বদলে গেলে আপনি কী করবেন? আপনার যদি ভার্চুয়াল ফাংশন থাকে, সমস্ত vftbl পয়েন্টার সম্ভবত ভুল হবে। আপনি যেখানে ফাইলটি ম্যাপ করেছেন সেখানে কীভাবে নিয়ন্ত্রণ করবেন? আপনি এটিকে একটি ঠিকানা দিতে পারেন, তবে এটি কেবল একটি ইঙ্গিত এবং কার্নেলটি অন্য বেস ঠিকানাটি চয়ন করতে পারে।
জেনস

আপনার স্থিতিশীল এবং স্পষ্টভাবে সংজ্ঞায়িত গাছের লেআউট থাকলে এটি পুরোপুরি কাজ করে। তারপরে আপনি প্রতিটি ক্ষেত্রে আপনার প্রাসঙ্গিক স্ট্রাক্টগুলিতে কাস্ট করতে পারেন এবং প্রতিবার "এমএমএপি শুরু ঠিকানা" এর অফসেট যুক্ত করে অভ্যন্তরীণ ফাইল পয়েন্টারগুলি অনুসরণ করতে পারেন। এটি
ইনোড

1

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


হাঁ। আমি সে সম্পর্কে ভাবছিলাম এবং সম্ভবত পরবর্তী কোনও প্রকাশে এটি চেষ্টা করব try আমার কাছে একমাত্র রিজার্ভেশনটি হ'ল প্রক্রিয়াটি I / O বিলম্বের তুলনায় অনেক কম, সুতরাং খুব বেশি সুবিধা নাও পেতে পারে।
জেবিএল

1

আমি মনে করি এমএমএপ সম্পর্কিত সর্বাধিক জিনিসটি এর সাথে অ্যাসিনক্রোনাস পড়ার জন্য সম্ভাব্য:

    addr1 = NULL;
    while( size_left > 0 ) {
        r = min(MMAP_SIZE, size_left);
        addr2 = mmap(NULL, r,
            PROT_READ, MAP_FLAGS,
            0, pos);
        if (addr1 != NULL)
        {
            /* process mmap from prev cycle */
            feed_data(ctx, addr1, MMAP_SIZE);
            munmap(addr1, MMAP_SIZE);
        }
        addr1 = addr2;
        size_left -= r;
        pos += r;
    }
    feed_data(ctx, addr1, r);
    munmap(addr1, r);

সমস্যাটি হ'ল এই মেমরিটি ফাইলটি Asap থেকে সিঙ্ক করতে হবে এমন একটি ইঙ্গিত দিতে আমি সঠিক MAP_FLAGS খুঁজে পাই না। আমি আশা করি এমএপ্পপলিট এমএমএপের জন্য সঠিক ইঙ্গিত দেয় (যেমন এটি কল থেকে ফেরার আগে সমস্ত বিষয়বস্তু লোড করার চেষ্টা করবে না, তবে এটি অ্যাসিঙ্কে করবে feed ফিড_ডাটা সহ)। কমপক্ষে এটি এই পতাকাটির সাথে আরও ভাল ফলাফল দেয় এমনকি ম্যানুয়াল জানিয়েছে যে এটি 2.6.23 থেকে এমএপ্প্রাইভেট ছাড়া কিছুই করে না।


1
আপনি অলস ইঙ্গিতগুলি প্রিপোপুলেট করার জন্য পতাকা posix_madviseসহWILLNEED চান ।
ShadowRanger

@ শ্যাডোএ্যাঞ্জার, যুক্তিসঙ্গত মনে হচ্ছে। যদিও আমি ম্যান পৃষ্ঠাটি আপডেট করে জানাতে চাই যে posix_madviseএটি অ্যাসিঙ্ক কল। এছাড়াও mlockযারা পুরো মেমরি অঞ্চলটি পৃষ্ঠা ত্রুটিগুলি ছাড়াই উপলব্ধ হয়ে উঠতে পারে ততক্ষণ পর্যন্ত অপেক্ষা করতে চান তাদের জন্য উল্লেখ করা ভাল to
ony
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.