আমি এমন একটি অ্যাপ্লিকেশনটিতে পারফরম্যান্স হটস্পটগুলি তদন্ত করছি যা এর 50% সময় মেমোমেভে (3) ব্যয় করে। অ্যাপ্লিকেশনটি বাছাই করা অ্যারেগুলিতে কয়েক মিলিয়ন 4-বাইট পূর্ণসংখ্যার সন্নিবেশ করায় এবং সন্নিবেশিত মানের জন্য স্থান তৈরি করতে "ডানদিকে" ডেটা স্থানান্তর করতে মেমমোভ ব্যবহার করে।
আমার প্রত্যাশা ছিল মেমোরি অনুলিপি করা খুব দ্রুত এবং আমি অবাক হয়েছি যে স্মৃতিচারণে এতটা সময় ব্যয় হয়। তবে আমার ধারণা ছিল যে মেমোমোভটি ধীর গতির কারণ এটি ওভারল্যাপিং অঞ্চলগুলিকে সরিয়ে নিয়েছে, যা মেমরির বৃহত পৃষ্ঠাগুলি অনুলিপি করার পরিবর্তে একটি শক্ত লুপে প্রয়োগ করা উচিত। মেমকি এবং মেমোমোভের মধ্যে পারফরম্যান্সের পার্থক্য রয়েছে কি না তা জানতে আমি একটি ছোট্ট মাইক্রোব্যাঙ্কমার্ক লিখেছি, মেমকিটি হাতছাড়া করার প্রত্যাশা করে।
আমি দুটি মেশিনে আমার বেঞ্চমার্ক দৌড়েছি (কোর আই 5, কোর আই 7) এবং দেখেছি যে মেমোমোভ আসলে মেম্পির চেয়ে দ্রুত, পুরানো কোর আই 7 এর চেয়ে দ্বিগুণ দ্রুত! এখন আমি ব্যাখ্যার সন্ধান করছি।
এই আমার মানদণ্ড। এটি মেমকিপি দিয়ে 100 এমবি অনুলিপি করে এবং তারপরে মেমমোভ দিয়ে প্রায় 100 এমবি স্থানান্তরিত করে; উত্স এবং গন্তব্য ওভারল্যাপিং হয়। উত্স এবং গন্তব্য জন্য বিভিন্ন "দূরত্ব" চেষ্টা করা হয়। প্রতিটি পরীক্ষা 10 বার চালানো হয়, গড় সময় মুদ্রিত হয়।
https://gist.github.com/cruppstahl/78a57cdf937bca3d062c
এখানে কোর আই 5-এ ফলাফল রয়েছে (লিনাক্স 3.5.0-54-জেনেরিক # 81 ~ যথাযথ 1-উবুন্টু এসএমপি x86_64 জিএনইউ / লিনাক্স, জিসিসি 4.6.3 (উবুন্টু / লিনারো 4.6.3-1ubuntu5) rac বন্ধনীগুলির সংখ্যাটি হ'ল উত্স এবং গন্তব্য মধ্যে দূরত্ব (ফাঁক আকার):
memcpy 0.0140074
memmove (002) 0.0106168
memmove (004) 0.01065
memmove (008) 0.0107917
memmove (016) 0.0107319
memmove (032) 0.0106724
memmove (064) 0.0106821
memmove (128) 0.0110633
মেমোভ একটি এসএসই অপ্টিমাইজড এসেম্ব্লার কোড হিসাবে প্রয়োগ করা হয়, পিছন থেকে সামনের দিকে অনুলিপি করে। এটি ক্যাশেতে ডেটা লোড করতে হার্ডওয়্যার প্রিফেচ ব্যবহার করে এবং এক্সএমএম রেজিস্টারে 128 বাইট অনুলিপি করে, তারপরে এগুলি গন্তব্যে সংরক্ষণ করে।
( memcpy-ssse3-back.S , লাইন 1650 ff)
L(gobble_ll_loop):
prefetchnta -0x1c0(%rsi)
prefetchnta -0x280(%rsi)
prefetchnta -0x1c0(%rdi)
prefetchnta -0x280(%rdi)
sub $0x80, %rdx
movdqu -0x10(%rsi), %xmm1
movdqu -0x20(%rsi), %xmm2
movdqu -0x30(%rsi), %xmm3
movdqu -0x40(%rsi), %xmm4
movdqu -0x50(%rsi), %xmm5
movdqu -0x60(%rsi), %xmm6
movdqu -0x70(%rsi), %xmm7
movdqu -0x80(%rsi), %xmm8
movdqa %xmm1, -0x10(%rdi)
movdqa %xmm2, -0x20(%rdi)
movdqa %xmm3, -0x30(%rdi)
movdqa %xmm4, -0x40(%rdi)
movdqa %xmm5, -0x50(%rdi)
movdqa %xmm6, -0x60(%rdi)
movdqa %xmm7, -0x70(%rdi)
movdqa %xmm8, -0x80(%rdi)
lea -0x80(%rsi), %rsi
lea -0x80(%rdi), %rdi
jae L(gobble_ll_loop)
মেমোমোভ কেন দ্রুত তবে মেমকি? আমি মেমকি থেকে মেমরি পৃষ্ঠাগুলি অনুলিপি করতে আশা করব, যা লুপিংয়ের চেয়ে অনেক দ্রুত হওয়া উচিত। সবচেয়ে খারাপ ক্ষেত্রে আমি মেমকিটি মেমোমোভের মতো দ্রুত হবে বলে আশা করব।
পিএস: আমি জানি যে আমি আমার কোডটিতে মেমপোয়ের সাথে মেমোমোভে প্রতিস্থাপন করতে পারি না। আমি জানি যে কোড নমুনা সি এবং সি ++ এর সাথে মিশে। এই প্রশ্নটি কেবলমাত্র একাডেমিক উদ্দেশ্যে।
আপডেট 1
আমি বিভিন্ন উত্তরের উপর ভিত্তি করে পরীক্ষাগুলির কিছু বৈকল্পিকতা চালিয়েছি।
- দু'বার মেমকি চালানোর সময়, দ্বিতীয় রানটি প্রথমটির চেয়ে দ্রুত হয়।
- যখন মেমকপির গন্তব্য বাফারটি "স্পর্শ" করে (
memset(b2, 0, BUFFERSIZE...)
) তখন মেমকপির প্রথম রানটিও দ্রুত হয়। - মেমকপি মেমোমোভের থেকে এখনও খানিকটা ধীর।
ফলাফল এখানে:
memcpy 0.0118526
memcpy 0.0119105
memmove (002) 0.0108151
memmove (004) 0.0107122
memmove (008) 0.0107262
memmove (016) 0.0108555
memmove (032) 0.0107171
memmove (064) 0.0106437
memmove (128) 0.0106648
আমার উপসংহার: @ অলিভার চার্লসওয়ার্থের একটি মন্তব্যের উপর ভিত্তি করে অপারেটিং সিস্টেমটিকে প্রথমবারের মতো মেমকি গন্তব্য বাফারটি অ্যাক্সেস করা মাত্রই শারীরিক স্মৃতিবদ্ধ করতে হবে (যদি কেউ "প্রমাণ" কীভাবে জানেন তবে দয়া করে একটি উত্তর যুক্ত করুন! )। এছাড়াও, @ ম্যাটস পিটারসন যেমন বলেছিলেন, মেমোমোচ হ'ল মেমপির চেয়ে ক্যাশে বন্ধুবান্ধব।
সমস্ত দুর্দান্ত উত্তর এবং মন্তব্যের জন্য ধন্যবাদ!