মেমকো মেমকির চেয়ে দ্রুত কেন?


90

আমি এমন একটি অ্যাপ্লিকেশনটিতে পারফরম্যান্স হটস্পটগুলি তদন্ত করছি যা এর 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

আমি বিভিন্ন উত্তরের উপর ভিত্তি করে পরীক্ষাগুলির কিছু বৈকল্পিকতা চালিয়েছি।

  1. দু'বার মেমকি চালানোর সময়, দ্বিতীয় রানটি প্রথমটির চেয়ে দ্রুত হয়।
  2. যখন মেমকপির গন্তব্য বাফারটি "স্পর্শ" করে ( memset(b2, 0, BUFFERSIZE...)) তখন মেমকপির প্রথম রানটিও দ্রুত হয়।
  3. মেমকপি মেমোমোভের থেকে এখনও খানিকটা ধীর।

ফলাফল এখানে:

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

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

সমস্ত দুর্দান্ত উত্তর এবং মন্তব্যের জন্য ধন্যবাদ!


4
আপনি মেমোমোভ কোডটি দেখেছেন, আপনি কি মেমকি কোডটি দেখেছেন?
অলিভার চার্লসওয়ার্থ

8
আমার প্রত্যাশাটি ছিল যে কপি করা মেমরিটি অত্যন্ত দ্রুত - কেবল যখন মেমরিটি L1 ক্যাশে থাকে। যখন ডেটা ক্যাশে ফিট করে না তখন আপনার অনুলিপি সম্পাদন কর্মক্ষমতা হ্রাস পাবে।
ম্যাক্সিম এগারুশকিন

4
বিটিডাব্লু, আপনি কেবল একটি শাখা অনুলিপি করেছেন memmove। উত্সটি গন্তব্যকে ওভারল্যাপ করে এবং গন্তব্যটি নীচের ঠিকানায় থাকে তখন এই শাখাটি স্থানান্তর পরিচালনা করতে পারে না।
ম্যাক্সিম এগারুশকিন

4
আমার কাছে লিনাক্স মেশিনটি অ্যাক্সেস করার সময় নেই, তাই আমি এই তত্ত্বটি এখনও পরীক্ষা করতে পারি না। তবে আরেকটি সম্ভাব্য ব্যাখ্যা ওভার কমিটিং ; আপনার memcpyলুপটি প্রথমবারের সামগ্রীগুলি b2অ্যাক্সেস করা হয়, সুতরাং ওএসকে এটি চলার সাথে সাথে শারীরিক স্মৃতিতে বাধ্য করতে হয়।
অলিভার চার্লসওয়ার্থ

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

উত্তর:


58

আপনার memmoveকলগুলি 2 থেকে 128 বাইটের সাথে মেমরিটি বদলে দিচ্ছে, যখন আপনার memcpyউত্স এবং গন্তব্য সম্পূর্ণ আলাদা। কোনওভাবে পারফরম্যান্স পার্থক্যের জন্য এটি অ্যাকাউন্টিং: আপনি যদি একই জায়গায় অনুলিপি করেন তবে আপনি memcpyসম্ভবত একটি স্মিজ দ্রুততর দেখবেন , যেমন আদর্শ আইটোন.কম :

memmove (002) 0.0610362
memmove (004) 0.0554264
memmove (008) 0.0575859
memmove (016) 0.057326
memmove (032) 0.0583542
memmove (064) 0.0561934
memmove (128) 0.0549391
memcpy 0.0537919

এর মধ্যে খুব কমই কিছু - প্রমাণ নেই যে মেমরি পৃষ্ঠায় ইতিমধ্যে ত্রুটিযুক্ত লেখার ক্ষেত্রে খুব বেশি প্রভাব রয়েছে, এবং আমরা অবশ্যই সময়ের অর্ধেকটি দেখতে পাচ্ছি না ... তবে এটি দেখায় যে memcpyআপেলের তুলনায় অযৌক্তিকভাবে ধীরে ধীরে ভুল করার কিছুই নেই there's আপেল জন্য।


আমি আশা করতাম যে সিপিইউ ক্যাশেগুলি তফাত সৃষ্টি করছে না কারণ আমার বাফারগুলি ক্যাশের চেয়ে অনেক বড়।
ক্রুপস্টাহল

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

4
@ টনি ডি - আমার উপসংহারটি ছিল আমার চেয়ে স্মার্ট লোকদের জিজ্ঞাসা করা;)
ক্রুপস্টাহল

4
এছাড়াও, আপনি যদি একই জায়গায় অনুলিপি করেন তবে কী হবে memcpyআবার প্রথমে?
অলিভার চার্লসওয়ার্থ

4
@ অলিভারচারসওয়ার্থ: প্রথম পরীক্ষার রানটি সর্বদা একটি গুরুত্বপূর্ণ হিট লাগে, তবে দুটি মেমকি টেস্ট করে: মেমকিপি 0.0688002 0.0583162 | মেমোমোভ 0.0577443 0.05862 0.0601029 ... দেখুন আদর্শ করুন. com
টনি

25

আপনি যখন ব্যবহার করছেন memcpyতখন লেখকদের ক্যাশে যেতে হবে। আপনি memmoveযখন একটি ছোট পদক্ষেপের অনুলিপি করার সময় যেখানে ব্যবহার করেন , আপনি যে মেমরিটি অনুলিপি করছেন তা ইতিমধ্যে ক্যাশে থাকবে (কারণ এটি 2, 4, 16 বা 128 বাইট "পিছনে" পড়েছিল)। memmoveগন্তব্যটি বেশ কয়েকটি মেগাবাইট (> 4 * ক্যাশের আকার) রয়েছে এমন চেষ্টা করার চেষ্টা করুন এবং আমি সন্দেহ করি (তবে পরীক্ষার জন্য বিরক্ত করা যায় না) আপনি একই ফলাফল পাবেন।

আমি গ্যারান্টি দিচ্ছি যে আপনি যখন বড় মেমরি অপারেশন করেন তখন সমস্ত ক্যাশে রক্ষণাবেক্ষণের বিষয়ে।


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

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

15

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

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

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

আপনি হয় আসলে আপনি যা করছেন তা বেঞ্চমার্ক করতে পারেন বা সমস্যাটিকে উপেক্ষা করতে পারেন এবং সি লাইব্রেরির জন্য করা মানদণ্ডের উপর নির্ভর করতে পারেন।

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

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


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

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

4
আপনি একটি মাইক্রো বেঞ্চমার্ক ব্যবহার করছেন এবং আপনার মেমকোপি এবং মেমোমোভ একই ডেটা শিফটও নেই। মেমরির সঠিক অবস্থানগুলি যা আপনি যে ডেটাতে অবস্থান করছেন তা ক্যাশে করার ক্ষেত্রে এবং সিপিইউকে মেমরির জন্য কতগুলি রাউন্ড ট্রিপ করতে পারে তার একটি তাত্পর্য তৈরি করে।
user3710044

যদিও এই উত্তরটি সঠিক, এটি আসলে এটি কেন ধীরে ধীরে ধীরে ধীরে তা ব্যাখ্যা করে না , এটি মূলত বলছে "এটি ধীর কারণ কারণ কিছু ক্ষেত্রে এটি ধীর হতে পারে"।
অলিভার চার্লসওয়ার্থ

আমি বলছি যে একই পরিস্থিতিতে, মেমরির একই লেআউট সহ মাপদণ্ডের অনুলিপি / সরানোর জন্য মেমরি একই হবে কারণ প্রয়োগগুলি একই। সমস্যাটি মাইক্রোব্যাঙ্কমার্কে রয়েছে।
user3710044

2

"মেমকো মেমোমোভের চেয়ে বেশি দক্ষ" " আপনার ক্ষেত্রে, আপনি দুটি কার্য সম্পাদন করার সময় আপনি সম্ভবত ঠিক একই জিনিসটি করছেন না।

সাধারণভাবে, আপনাকে কেবল যদি ব্যবহার করতে হয় তবে ব্যবহার করুন mem উত্স এবং গন্তব্য অঞ্চলগুলি অতিরিক্ত-ল্যাপিংয়ের খুব যুক্তিসঙ্গত সুযোগ থাকলে এটি ব্যবহার করুন।

তথ্যসূত্র: https://www.youtube.com/watch?v=Yr1YnOVG-4g ডাঃ জেরি কেইন, (স্ট্যানফোর্ড ইন্ট্রো সিস্টেমের বক্তৃতা - 7) সময়: 36:00

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