মেমরিতে অস্থায়ী ম্যাট্রিক্স তৈরি না করে ম্যাট্রিক্সকে কীভাবে 'অনুলিপি করুন' যার ফলে স্মৃতি ওভারফ্লো হয়েছিল?


9

অনেক বড় বরাদ্দ মেমরির ক্ষেত্রে একটি ম্যাট্রিক্স নির্ধারণের মাধ্যমে, ম্যাটল্যাব এটি 'অনুলিপি করার' সময় কোনওভাবে এটির নকল করবে এবং ম্যাট্রিক্স যদি অনুলিপি করা যায় তবে মেমরির ওভারফ্লো হবে। এটি নমুনা কোড:

main_mat=zeros(500,500,2000);
n=500;
slice_matrix=zeros(500,500,n);
for k=1:4
    parfor i=1:n
        slice_matrix(:,:,i)=gather(gpuArray(rand(500,500)));
    end
    main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix; %This is where the memory will likely overflow
end

কোন পথে শুধু 'সম্পূর্ণ ধ্বংস' থেকে slice_matrixসম্মুখের main_matওভারহেড ছাড়া? আগাম ধন্যবাদ.

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

main_matআগে থেকে বরাদ্দ দেওয়া হলে ওভারফ্লো হয়েছিল। যদি (ছোট আকার) main_matদিয়ে আরম্ভ করা হয় main_mat=zeros(500,500,1);তবে ওভারফ্লোটি ঘটবে না, তবে ম্যাট্রিক্স বরাদ্দের আগে বরাদ্দ না করা হওয়ায় এটি ধীর হয়ে যাবে। এটি kবৃদ্ধি পরিসীমা হিসাবে কর্মক্ষমতা উল্লেখযোগ্যভাবে হ্রাস করবে ।


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

1
মতলব আসলে স্মৃতিটিকে নকল করছে বলে আপনার ইঙ্গিতটি কী? আপনি কি memoryফাংশন ব্যবহার করছেন ? টাস্ক-ম্যানেজার? মতলব থেকে একটি স্মৃতি ত্রুটি? কোডের কোন লাইনে এটি ঘটছে?
এলিয়াহু হারুন

আপনি কোডটি কোথায় মন্তব্য করেছিলেন তা দেখতে পেলাম, main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)সেখানেই মেমরির ওভারফ্লো সমস্যাটি ঘটে। এটি যাচাই করা হয়েছিল যখন আমি main_matআগে থেকেই বরাদ্দ দিয়েছিলাম, এটি উপচে পড়বে, যদি আমি না করি তবে তা হবে না। মতলব 'স্মৃতি ত্রুটির বাইরে' ফিরে আসবে।
গ্রেগর ইস্যাক

আপনার 500x500x2000 ম্যাট্রিক্স মেমরি ফিট করে? এটি ~ 4 জিবি। অ্যারেতে লেখার সময় কেবল মেমরির ত্রুটি কেন ঘটতে পারে তার জন্য stackoverflow.com/q/51987892/7328782 দেখুন ।
ক্রিস লুয়েংগো

আপনার সমস্যাটি আরও ভালভাবে বুঝতে, আপনি কি একটি h=h+slice_matrix(end)পূর্বে main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix;andোকাতে পারেন (এবং এইচ 0 দিয়ে আরম্ভ)? আমার সন্দেহ হয় যে এই নতুন যুক্ত লাইনটি ইতিমধ্যে আপনার স্মৃতি সমস্যার কারণ হয়ে দাঁড়াবে।
ড্যানিয়েল

উত্তর:


4

মূল সমস্যাটি হ'ল সংখ্যাগুলি শূন্যের চেয়ে বেশি স্থান নেয়। অনেকটা main_mat=zeros(500,500,2000);সময় main_mat = rand(500,500,2000);নেওয়ার সময় সামান্য র‌্যাম লাগে , আপনি জিপিইউ বা পার্ফার ব্যবহার করেন না কেন (আসলে পারফোর আপনাকে আরও র‌্যাম ব্যবহার করবে)। সুতরাং এটি মেমরির কোনও অপ্রাকৃত swe ড্যানিয়েলের নীচের লিঙ্কটি অনুসরণ করে, মনে হচ্ছে যে শূন্যগুলির অ্যাসাইনমেন্ট কেবল মেমরির জন্য পয়েন্টার তৈরি করে এবং শারীরিক স্মৃতি কেবল তখনই পূরণ করা হয় যখন আপনি "সংখ্যার" জন্য ম্যাট্রিক্স ব্যবহার করেন। এটি অপারেটিং সিস্টেম দ্বারা পরিচালিত হয়। এবং এটি উইন্ডোজ, ম্যাক এবং লিনাক্সের জন্য আশা করা হয়, হয় আপনি এটি মাতলাব বা সি এর মতো অন্যান্য ভাষার সাথে করেন either


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

3
আমি এটি ব্যাখ্যা করার মতো কিছু পেয়েছি: স্ট্যাকওভারফ্লো.com
ড্যানিয়েল

দুর্দান্ত উত্তর! ধন্যবাদ।
জেএলএভ

@ গ্রেগর: আমার ধারণা এটি নিশ্চিত onesকরার জন্য zeros, পরিবর্তে এটি ব্যবহার করে দেখুন এটি নিশ্চিত করে যে স্বতন্ত্রভাবে ফাংশনটি কল করার সময় মেমরিটি আসলে বরাদ্দ হয়েছিল।
ড্যানিয়েল

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

1

অপসারণ parforসম্ভবত আপনার সমস্যার সমাধান করবে।

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

এর অর্থ হ'ল যে প্রতিটি প্রক্রিয়া শুরু হয়েছিল parforতার নিজস্ব কপি থাকা দরকার slice_matrixযা আপনার প্রোগ্রাম দ্বারা ব্যবহৃত প্রচুর পরিমাণে মেমরির কারণ।

এটি কখন এবং কখন ব্যবহার করবেন সে সম্পর্কে ম্যাটল্যাব ডকুমেন্টেশনে " কখন ব্যবহার করবেন সিদ্ধান্ত নিন"parfor দেখুন parfor


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

@ গ্রেগরিস্যাক: আমি আপনার উদাহরণ কোডটি দিয়েছিলাম, জানতাম না যে আপনি আসলে এর ভিতরে অনেক কাজ করেছেন parfor। যদি তা হয় তবে হ্যাঁ, এটি সম্ভবত কার্যকর। - সম্ভবত যদি slice_matrixএটি না gpuarrayহয় তবে এটি অ্যাসাইনমেন্টে অনুলিপি করা হবে না।
ক্রিস লুয়েংগো

হুমম এমনকি যদি slice_matrixনা হয় তবে gpuArrayআমি ওভারফ্লো লক্ষণ পাচ্ছি। আমি এই প্রশ্নটি খুলতে দেব, আসুন দেখি কোনও বিকল্প সমাধান আছে কিনা। যদিও উত্তরের জন্য ধন্যবাদ!
গ্রেগর ইস্যাক

0

আমি ধরে নিলাম যে আপনার কোডটি কেবলমাত্র একটি নমুনা কোড এবং এটি rand()আপনার এমভিইতে একটি কাস্টমকে উপস্থাপন করে। সুতরাং মতলবটিতে মেমরির ব্যবহারের জন্য কয়েকটি ইঙ্গিত এবং কৌশল রয়েছে।

দ্য ম্যাথ ওয়ার্কস প্রশিক্ষণ হ্যান্ডবুকগুলির একটি স্নিপেট রয়েছে:

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

প্রথমটি হ'ল আপনার কোডটির (মেমরি) দক্ষতা যাচাই করা। এমনকি দুর্দান্ত প্রোগ্রামারগুলির কোডটি (সামান্য) মস্তিষ্ক শক্তি দিয়ে আরও অনুকূলিত করা যেতে পারে। স্মৃতিশক্তির দক্ষতা সম্পর্কিত কয়েকটি ইঙ্গিত এখানে রইল

  • মতলব এর nativ vectorization বানানো ব্যবহার, যেমন sum(X,2), mean(X,2),std(X,[],2)
  • নিশ্চিত করুন যে মাতলাবকে ম্যাট্রিকগুলি প্রসারিত করতে হবে না ( অন্তর্নিহিত সম্প্রসারণটি সম্প্রতি পরিবর্তন করা হয়েছিল)। এটি ব্যবহার করতে আরও দক্ষ হতে পারেbsxfun
  • স্থানে-অপারেশন ব্যবহার করুন, উদাহরণস্বরূপ x = 2*x+3পরিবর্তেx = 2*x+3
  • ...

সচেতন থাকুন যে মেমরির ব্যবহার সম্পর্কে সর্বোত্তম আপনি যদি গণনার সময় হ্রাস করতে চান তবে একই নয়। সুতরাং, আপনি শ্রমিকের সংখ্যা হ্রাস করার বিষয়টি বিবেচনা করতে পারেন বা parfor-লুপটি ব্যবহার থেকে বিরত থাকতে পারেন। (যেমন parforভাগ করা মেমরি ব্যবহার করতে পারে না, প্যারালাল টুলবক্স ব্যবহার করে কোনও অনুলিপি-অনুলিপি বৈশিষ্ট্য নেই।

আপনি যদি আপনার স্মৃতিচারণটি ঘনিষ্ঠভাবে দেখতে চান তবে কী পাওয়া যায় এবং এটি মাতলাব ব্যবহার করতে পারেন, পরীক্ষা করে দেখুন feature('memstats')। আপনি কি আকর্ষণীয় মনে হয় ভার্চুয়াল মেমরি যে

পুরো এমএটিএলবি প্রক্রিয়াটির সাথে সম্পর্কিত মোট এবং উপলব্ধ মেমরি। এটি প্রসেসরের আর্কিটেকচার এবং অপারেটিং সিস্টেম দ্বারা সীমাবদ্ধ। বা এই আদেশ ব্যবহার করুন [user,sys] = memory

কুইক সাইড নোড : মতলব মেট্রিসিতে মেমরির ধারাবাহিকভাবে সঞ্চয় করে। বড় ম্যাট্রিক্সের জন্য আপনার কাছে র‍্যামের একটি বৃহত ব্লক থাকা দরকার। আপনি ভেরিয়েবলগুলি বরাদ্দ করতে চান সেই কারণও কারণ এগুলি পরিবর্তন করে মাতলাবকে প্রতি ম্যাট্রিক্সকে র‌্যামের বর্তমান মাপের চেয়ে আরও বড় স্পষ্টে অনুলিপি করতে বাধ্য করে।

আপনার যদি সত্যিই মেমরির সমস্যা থাকে তবে আপনি কেবলমাত্র ডাটা প্রকারের কলাটি খনন করতে চান - নিম্ন স্তরের ভাষাগুলিতে যেমন প্রয়োজন। যেমন আপনি শুরু থেকে সরাসরি একক নির্ভুলতা ব্যবহার করে আপনার মেমরির ব্যবহার অর্ধেক কেটে ফেলতে পারেন main_mat=zeros(500,500,2000,'single');- বিটিডব্লিউ, এটি আরও rand(...,'single')বেশি দেশীয় ফাংশনগুলির সাথেও কাজ করে - যদিও আরও কিছু পরিশীলিত মাতলাব ফাংশনগুলির জন্য টাইপ ডাবল ইনপুট প্রয়োজন যা আপনি করতে পারেন আবার উজান।


0

যদি আমি সঠিকভাবে বুঝতে পারি তবে আপনার মূল সমস্যাটি হ'ল এটি parforমেমরি ভাগ করার অনুমতি দেয় না। প্রতিটি পারফর্ম কর্মীকে প্রায় একটি পৃথক মতলব উদাহরণ হিসাবে ভাবেন।

এটির জন্য মূলত কেবলমাত্র একটি কাজ রয়েছে যা আমি জানি (যা আমি কখনই চেষ্টা করি নি), এটি ফাইল এক্সচেঞ্জের 'শেয়ারড ম্যাট্রিক্স': https://ch.mathworks.com/matlabcentral/fileexchange/28572-sharedmatrix

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


0

আপনি নিম্নলিখিত কোড ব্যবহার করতে পারেন। আপনার আসলে স্লাইস_ম্যাট্রিক্সের দরকার নেই

main_mat=zeros(500,500,2000);
n=500;
slice_matrix=zeros(500,500,n);
for k=1:4
   parfor i=1:n
       main_mat(:,:,1+(k-1)*n + i - 1) = gather(gpuArray(rand(500,500)));
   end
   %% now you don't need this main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix; %This is where the memory will likely overflow
end

আপনি পারফার লুপের ভিতরে এটি করতে পারবেন না
গ্রেগর ইস্যাক

তুমি কি চেষ্টা করেছ?
mayank1513

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