ফরটারনে মেমোরির ব্যবহার যখন পয়েন্টার সহ উত্পন্ন ধরণের অ্যারের ব্যবহার করে


13

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

program test
implicit none

  type nodesType
    integer:: nnodes
    integer,dimension(:),pointer:: nodes 
  end type nodesType

  type nodesType2
    integer:: nnodes
    integer,dimension(4):: nodes 
  end type nodesType2

  type(nodesType),dimension(:),allocatable:: FaceList
  type(nodesType2),dimension(:),allocatable:: FaceList2

  integer:: n,i

  n = 100000000

  print *, '1'
  read(*,*)
  allocate(FaceList(n))
  do i=1,n
    FaceList(i)%nnodes = 4
    allocate(FaceList(i)%nodes(4))
    FaceList(i)%nodes(1:4) = (/1,2,3,4/)
  end do
  print *, '2'
  read(*,*)

  do i=1,n
    deallocate(FaceList(i)%nodes)
  end do
  deallocate(FaceList)

  allocate(FaceList2(n))
  do i=1,n
    FaceList2(i)%nnodes = 4
    FaceList2(i)%nodes(1:4) = (/1,2,3,4/)
  end do
  print *, '3'
  read(*,*)

end program test

পটভূমি স্থানীয় গ্রিড পরিশোধন। আমি সহজে যুক্ত করতে এবং মুছে ফেলার জন্য লিঙ্কযুক্ত তালিকাটি বেছে নিয়েছি। নোডের সংখ্যা ডিফল্ট হিসাবে 4 হয় তবে স্থানীয় পরিশোধনগুলির উপর নির্ভর করে আরও বেশি হয়ে উঠতে পারে।


1
"প্রথম উপায়" যতটা সম্ভব ফাঁস হওয়া উচিত যতটা সম্ভব ফাঁস হওয়ার প্রবণতা রয়েছে (অ্যারেগুলি অবশ্যই স্পষ্টভাবে deallocated করা উচিত, যেমন আপনি করেছিলেন) পারফরম্যান্সের পার্থক্য আপনি দেখতে পাচ্ছেন। এটি ব্যবহারের একমাত্র কারণটি হবে ফরট্রান 95-এর কঠোর আনুগত্যের জন্য der ।
stally

1
এটি করার কারণটি হ'ল কিছু মুখের মধ্যে 4 টিরও বেশি নোড থাকতে পারে।
ক্রিস

তারপরে অবশ্যই তা বোধগম্য হয়। আমি ধরে নিয়েছিলাম 4 একটি ধ্রুবক ছিল।
stally

উত্তর:


6

ফোর্টরান সংকলকরা কীভাবে কাজ করে তা আমি আসলে জানি না, তবে ভাষার বৈশিষ্ট্যগুলির ভিত্তিতে আমি একটি অনুমান নিতে পারি।

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

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


হ্যাঁ তবে মেটাডেটা যুক্তিটি উভয় ক্ষেত্রেই সত্য নয়?
stally

@ স্টালি নো, লক্ষ্য করুন যে দ্বিতীয় nপদ্ধতির জন্য প্রথম পদ্ধতির প্রয়োজনীয় পয়েন্টারগুলির বিপরীতে একটি পয়েন্টার প্রয়োজন।
অরন আহমদিয়া

আমি কিছু পটভূমি তথ্য যুক্ত করেছি। স্থায়ীভাবে একটি উপরের সীমানা বরাদ্দ করার জন্য আপনার পরামর্শটি ইতিমধ্যে ভাল উন্নতি। উপরের চৌম্বকটি 8, তবে সংখ্যাগরিষ্ঠটির 4 টি হবে, কেবলমাত্র একটি অল্প শতাংশের 5,6,7 বা 8 থাকবে So সুতরাং স্মৃতি এখনও নষ্ট হয় ...
ক্রিস

@ ক্রিস: আপনি দুটি তালিকা তৈরি করতে পারবেন, একটিতে 4, এবং একটি 8 টি নোড দিয়ে?
পেড্রো

সম্ভবত। এটি একটি ভাল আপস বলে মনে হচ্ছে।
ক্রিস

5

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

প্রতিটি নোডের জন্য একটি ছোট অংশ বরাদ্দ এড়াতে, আপনি প্রতিটি নোড একটি প্রাক বরাদ্দ অ্যারের একটি অংশ বরাদ্দ চেষ্টা করতে পারেন :

integer :: finger
indeger, dimension(8*n) :: theNodes

finger = 1
do i=1,n
    FaceList(i)%nodes => theNodes(finger:finger+FaceList(i)%nnodes-1)
    finger = finger + FaceList(i)%nnodes
end do

আমার ফোর্টরান কিছুটা মরিচা, তবে নীতির নীতিগতভাবে না হলে উপরের কাজ করা উচিত।

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


এটি সাহায্য করে তবে কেবল সামান্যই। সমস্যাটি হ'ল এটি কোনও একক পয়েন্টার নয়, তবে পয়েন্টারগুলির একটি গতিশীল অ্যারে: ফেসলিস্ট (i)% নোড (1: ফেসলিস্ট (i)% nnodes) => নোটস (আঙুল: আঙুল + ফেসলিস্ট (i)% nnodes-1)। এটি প্রাক বরাদ্দ করা অ্যারের আকারের জন্য একটি তীক্ষ্ণ প্রাক্কলনকেও বোঝায়।
ক্রিস

@ ক্রিস: আমি নিশ্চিত যে আমি সম্পূর্ণ বুঝতে পেরেছি না ... "পয়েন্টারগুলির গতিশীল অ্যারে" বলতে কী বোঝ? ক্ষেত্রটি nodesType%nodesগতিশীল অ্যারেগুলির জন্য একটি পয়েন্টার।
পেড্রো

0

উহু. এটিই আমি একই সমস্যায় ভুগছি। এই প্রশ্নটি খুব পুরানো, তবে আমি একটু আলাদা কোড শৈলীর পরামর্শ দিই। আমার সমস্যাটি নিম্নলিখিত কোডের অনুসারে প্রাপ্ত ডেটা টাইপের ক্ষেত্রে বরাদ্দযোগ্য স্টেটমেন্ট অ্যারে ছিল।

type :: node
  real*4,dimension(:),allocatable :: var4
  real*8,dimension(:),allocatable :: var8
end type node

type(node),dimension(:),allocatable :: nds

imax = 5000
allocate(nds(imax))

কিছু পরীক্ষা থেকে, আমি নিশ্চিত হয়েছি যে আমি যদি চারটি ক্ষেত্রে সম্পর্কে অনুসরণীয় কোড হিসাবে উত্পন্ন প্রকারে বরাদ্দযোগ্য স্টেটমেন্ট বা পয়েন্টার স্টেটমেন্ট ব্যবহার করি তবে মেমরি ফুটো খুব বড় ঘটে। আমার ক্ষেত্রে, আমি 520 এমবি আকারের ফাইলটি লাল করে ফেলি। তবে মেমরির ব্যবহারটি ইন্টেল ফোর্টারান কমপ্লায়ারের রিলিজ মোডে 4 জিবি ছিল। এটি 8 গুণ বড়!

!(case 1) real*4,dimension(:),allocatable :: var4
!(case 2) real*4,dimension(:),pointer :: var4
!(case 3) real*4,allocatable :: var4(:,:)

!(case 4) 
type :: node(k)
  integer,len :: k = 4
  real*4 :: var4(k)
end type node

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

real*4,dimension(:,:),allocatable :: var4 
! array index = (Num. of Nodes, Num. of Variables)

বা এই স্টাইলটি কেমন?

integer,dimension(:),allocatable :: NumNodes ! (:)=Num. of Cell or Face or etc.
integer,dimension(:),allocatable :: Node     ! (:)=(Sum(NumNodes))

নুমনোড ভেরিয়েবল মানে প্রতিটি মুখের নোডের সংখ্যা এবং নোড ভেরিয়েবল হ'ল নোম সংখ্যাগুলি নুমনোড ভেরিয়েবলের সাথে মেলে। সম্ভবত এই কোড শৈলীতে মেমরি ফাঁস ঘটে না, আমি মনে করি।

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