বড় অ্যারে স্টোরেজ (ফ্ল্যাট বাইনারি ফাইলগুলির পরিবর্তে) এর জন্য এইচডিএফ 5 ব্যবহার করার কোনও বিশ্লেষণের গতি বা মেমরির ব্যবহারের সুবিধা রয়েছে কি?


97

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

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

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

আমি পিটবেবলস এবং এইচ 5 পিস উভয়ই অন্বেষণ করেছি এবং আমার উদ্দেশ্যটির জন্য এখন পর্যন্ত কোনওটির উপকারিতা দেখিনি।


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

ধন্যবাদ আমি সম্মত হই যে এইচ 5 পি একটি ম্যাসেম্যাপের মতো ডেটাসেট ফেরত দেয়। তবে, আপনি যদি h5py ডেটাসেটের একটি টুকরো করেন তবে এটি একটি অদ্ভুত অ্যারে প্রদান করে, যা আমি বিশ্বাস করি (?) এর অর্থ ডেটা অযথা মেমরিতে রাখা হয়েছে। একটি স্মৃতিচারণ সম্ভব হলে মূল মেমম্যাপে একটি ভিউ দেয়। অন্য কথায়: type(cube)দেয় h5py._hl.dataset.Dataset। যদিও type(cube[0:1,:,:])দেয় numpy.ndarray
কালেব

তবে গড় পড়ার সময় সম্পর্কে আপনার বক্তব্য আকর্ষণীয়।
কালেব

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

4
"যদি আমি একটি ফ্ল্যাট বাইনারি ফাইলের একটি numpy memmap যেভাবেই, আমি একটি দৃশ্য, যা ডিস্কে ডেটা রাখবে পেতে পারেন" - যে সত্য হতে পারে, কিন্তু আপনি আসলে করতে চান তাহলে কি আজ না হোক কাল তারপর যে অ্যারের মধ্যে মান নিয়ে কিছু আপনাকে এগুলি র‍্যামে লোড করতে হবে। একটি মেমরি-ম্যাপযুক্ত অ্যারে কেবল কিছু এনক্যাপসুলেশন সরবরাহ করে যাতে আপনাকে কখন কখন ডেটা পড়বে বা এটি আপনার সিস্টেমের স্মৃতিশক্তি সক্ষমতা ছাড়িয়ে যাবে কিনা তা নিয়ে ভাবতে হবে না। কিছু পরিস্থিতিতে স্মৃতিযুক্ত অ্যারের নেটিভ ক্যাচিং আচরণ প্রকৃতপক্ষে খুব suboptimal হতে পারে ।
ali_m

উত্তর:


162

এইচডিএফ 5 সুবিধা: সংস্থাটি, নমনীয়তা, আন্তঃব্যবহার্যতা

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

এইচডিএফের আর একটি সুবিধা হ'ল ডেটাসেটগুলি হয় স্থির আকার বা নমনীয় আকারের হতে পারে। অতএব, সম্পূর্ণ নতুন অনুলিপি তৈরি না করেই একটি বড় ডেটাসেটে ডেটা যুক্ত করা সহজ।

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

একটি বড় অ্যারের জন্য এইচডিএফ সুবিধা: একটি স্বেচ্ছাসেবী স্লাইসের দ্রুত I / O I

ঠিক তেমনি টিএল / ডিআর: GB 8 জিবি 3 ডি অ্যারের জন্য, কোনও অক্ষ সহ একটি "পূর্ণ" স্লাইস পড়ার জন্য অবনমিত এইচডিএফ 5 ডেটাসেটের সাথে 20 সেকেন্ড, এবং 0.3 সেকেন্ড (সেরা-কেস) থেকে তিন ঘণ্টারও বেশি সময় (সবচেয়ে খারাপ ক্ষেত্রে) সময় লাগে for একই তথ্য একটি স্মৃতিযুক্ত অ্যারে।

উপরের তালিকাভুক্ত জিনিসগুলি বাদে, "চুঙ্কড" * অন ডিস্ক ডেটা ফর্ম্যাট যেমন এইচডিএফ 5 এর আরও একটি বড় সুবিধা রয়েছে: অন-ডিস্কের ডেটা আরও সংকীর্ণ হওয়ায় একটি স্বেচ্ছাসেবক স্লাইস (স্বেচ্ছাসেবীর উপর জোর দেওয়া) পড়া সাধারণত সাধারণত আরও দ্রুত হবে as গড়

*(এইচডিএফ 5 টি খণ্ডিত ডেটা ফর্ম্যাট হতে হবে না It এটি ছানকে সমর্থন করে তবে এটির প্রয়োজন হয় না In আসলে h5py, যদি আমি সঠিকভাবে স্মরণ করি তবে ডেটাসেট তৈরি করার জন্য ডিফল্টটি খণ্ডন করা নয়।)

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

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


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

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

আপনি যদি কোটির বাইরে গণনা করতে চান, তবে আপনি সহজেই ট্যাবুলার ডেটার সাথে pandasবা এর জন্য সহজেই পারেন pytables। এটির সাহায্যে h5py(বড় বড় এনডি অ্যারেগুলির জন্য ভাল) এটি সম্ভব , তবে আপনাকে একটি স্পর্শ নিম্ন স্তরে নামতে হবে এবং পুনরাবৃত্তিটি নিজেই পরিচালনা করতে হবে।

যাইহোক, নাম্পির মতো-বহি-কোর-গুনের ভবিষ্যত হ'ল ব্লেজ। আপনি যদি সত্যিই সেই রুটটি নিতে চান তবে এটি একবার দেখুন


"আনচানড" মামলা

প্রথমে, ডিস্কে লিখিত একটি 3D সি-অর্ডারযুক্ত অ্যারে বিবেচনা করুন ( arr.ravel()জিনিসগুলি আরও দৃশ্যমান করার জন্য, আমি ফলাফলটি কল করে এবং মুদ্রণের মাধ্যমে এটিকে অনুকরণ করি ):

In [1]: import numpy as np

In [2]: arr = np.arange(4*6*6).reshape(4,6,6)

In [3]: arr
Out[3]:
array([[[  0,   1,   2,   3,   4,   5],
        [  6,   7,   8,   9,  10,  11],
        [ 12,  13,  14,  15,  16,  17],
        [ 18,  19,  20,  21,  22,  23],
        [ 24,  25,  26,  27,  28,  29],
        [ 30,  31,  32,  33,  34,  35]],

       [[ 36,  37,  38,  39,  40,  41],
        [ 42,  43,  44,  45,  46,  47],
        [ 48,  49,  50,  51,  52,  53],
        [ 54,  55,  56,  57,  58,  59],
        [ 60,  61,  62,  63,  64,  65],
        [ 66,  67,  68,  69,  70,  71]],

       [[ 72,  73,  74,  75,  76,  77],
        [ 78,  79,  80,  81,  82,  83],
        [ 84,  85,  86,  87,  88,  89],
        [ 90,  91,  92,  93,  94,  95],
        [ 96,  97,  98,  99, 100, 101],
        [102, 103, 104, 105, 106, 107]],

       [[108, 109, 110, 111, 112, 113],
        [114, 115, 116, 117, 118, 119],
        [120, 121, 122, 123, 124, 125],
        [126, 127, 128, 129, 130, 131],
        [132, 133, 134, 135, 136, 137],
        [138, 139, 140, 141, 142, 143]]])

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

In [4]: arr.ravel(order='C')
Out[4]:
array([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,
        13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,
        26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
        39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,
        52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
        65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,
        78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
        91,  92,  93,  94,  95,  96,  97,  98,  99, 100, 101, 102, 103,
       104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
       117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
       130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143])

সেরা ক্ষেত্রে, প্রথম অক্ষ বরাবর একটি স্লাইস নেওয়া যাক। লক্ষ্য করুন যে এটি অ্যারের প্রথম 36 টি মান। এটি খুব দ্রুত পড়া হবে! (এক সন্ধান, এক পড়া)

In [5]: arr[0,:,:]
Out[5]:
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23],
       [24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35]])

একইভাবে, প্রথম অক্ষের সাথে পরবর্তী স্লাইসটি কেবল পরবর্তী 36 টি মান হবে। এই অক্ষ বরাবর একটি সম্পূর্ণ স্লাইস পড়তে, আমাদের কেবল একটি seekঅপারেশন প্রয়োজন । যদি আমরা সমস্ত কিছু পড়তে যাচ্ছি এই অক্ষটি বরাবর বিভিন্ন টুকরা হয়, তবে এটি সঠিক ফাইল কাঠামো।

যাইহোক, আসুন সবচেয়ে খারাপ পরিস্থিতি বিবেচনা করুন: শেষ অক্ষ বরাবর একটি স্লাইস।

In [6]: arr[:,:,0]
Out[6]:
array([[  0,   6,  12,  18,  24,  30],
       [ 36,  42,  48,  54,  60,  66],
       [ 72,  78,  84,  90,  96, 102],
       [108, 114, 120, 126, 132, 138]])

এই স্লাইসটি পড়তে, আমাদের 36 টি সেকস এবং 36 টি পাঠ্য প্রয়োজন, কারণ সমস্ত মান ডিস্কে পৃথক করা হয়। এদের কেউই সংলগ্ন নয়!

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

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


সাধারণ "খণ্ডিত" কেস

ধরা যাক আমরা 3x অ্যারের 2x2x2 "অংশগুলি" ডিস্কে সংহত ব্লক হিসাবে সঞ্চয় করি। অন্য কথায়, এর মতো কিছু:

nx, ny, nz = arr.shape
slices = []
for i in range(0, nx, 2):
    for j in range(0, ny, 2):
        for k in range(0, nz, 2):
            slices.append((slice(i, i+2), slice(j, j+2), slice(k, k+2)))

chunked = np.hstack([arr[chunk].ravel() for chunk in slices])

সুতরাং ডিস্কের ডেটাটি দেখতে এমন হবে chunked:

array([  0,   1,   6,   7,  36,  37,  42,  43,   2,   3,   8,   9,  38,
        39,  44,  45,   4,   5,  10,  11,  40,  41,  46,  47,  12,  13,
        18,  19,  48,  49,  54,  55,  14,  15,  20,  21,  50,  51,  56,
        57,  16,  17,  22,  23,  52,  53,  58,  59,  24,  25,  30,  31,
        60,  61,  66,  67,  26,  27,  32,  33,  62,  63,  68,  69,  28,
        29,  34,  35,  64,  65,  70,  71,  72,  73,  78,  79, 108, 109,
       114, 115,  74,  75,  80,  81, 110, 111, 116, 117,  76,  77,  82,
        83, 112, 113, 118, 119,  84,  85,  90,  91, 120, 121, 126, 127,
        86,  87,  92,  93, 122, 123, 128, 129,  88,  89,  94,  95, 124,
       125, 130, 131,  96,  97, 102, 103, 132, 133, 138, 139,  98,  99,
       104, 105, 134, 135, 140, 141, 100, 101, 106, 107, 136, 137, 142, 143])

এবং কেবল এটি দেখানোর জন্য যে তারা 2x2x2 ব্লক arr, লক্ষ্য করুন যে এগুলি এর প্রথম 8 টি মান chunked:

In [9]: arr[:2, :2, :2]
Out[9]:
array([[[ 0,  1],
        [ 6,  7]],

       [[36, 37],
        [42, 43]]])

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

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


সঙ্গে এলোমেলোভাবে অ্যারে h5py

ডিফল্টরূপে, h5pyডিস্কে খণ্ডিত এইচডিএফ ফাইল তৈরি করে না (আমার pytablesবিপরীতে মনে হয়) does আপনি যদি chunks=Trueডেটাসেট তৈরি করার সময় নির্দিষ্ট করে থাকেন তবে আপনি ডিস্কে একটি খাঁটি অ্যারে পাবেন।

দ্রুত, ন্যূনতম উদাহরণ হিসাবে:

import numpy as np
import h5py

data = np.random.random((100, 100, 100))

with h5py.File('test.hdf', 'w') as outfile:
    dset = outfile.create_dataset('a_descriptive_name', data=data, chunks=True)
    dset.attrs['some key'] = 'Did you want some metadata?'

নোট যা আমাদের জন্য স্বয়ংক্রিয়ভাবে একটি খণ্ড আকার বেছে নিতে chunks=Trueবলে h5py। আপনি যদি আপনার সর্বাধিক সাধারণ ব্যবহারের ক্ষেত্রে সম্পর্কে আরও জানেন তবে আপনি শেপের আকার / আকৃতিটিকে একটি শেপ টিপল (যেমন (2,2,2)উপরের সাধারণ উদাহরণে) নির্দিষ্ট করে নির্দিষ্ট করতে পারেন । এটি আপনাকে একটি নির্দিষ্ট অক্ষ বরাবর পাঠগুলি আরও দক্ষ করে তুলতে বা নির্দিষ্ট আকারের পঠন / লেখার জন্য অনুকূল করতে দেয়।


I / O পারফরম্যান্স তুলনা

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

আমি প্রতিটি রানের মধ্যে সমস্ত ওএস ক্যাশে সাফ করে দিয়েছি , তাই আমরা "শীতল" পারফরম্যান্সটি দেখছি।

প্রতিটি ফাইল প্রকারের জন্য, আমরা প্রথম অক্ষের সাথে একটি "পূর্ণ" এক্স-স্লাইস এবং শেষ অক্ষের সাথে একটি "পূর্ণ" জেড-স্লাইজে পড়া পরীক্ষা করব। ফোর্টরান-অর্ডারযুক্ত মেমপ্যাটেড অ্যারের জন্য, "এক্স" স্লাইসটি সবচেয়ে খারাপ পরিস্থিতি এবং "জেড" স্লাইসটি সেরা ক্ষেত্রে।

ব্যবহৃত কোডটি একটি সংক্ষেপে রয়েছে ( hdfফাইল তৈরি করা সহ )। আমি এখানে ব্যবহৃত ডেটা সহজেই ভাগ করতে পারি না তবে আপনি এটি একই আকারের শূন্যের একটি অ্যারে ( 621, 4991, 2600)এবং টাইপ করে সিমুলেট করতে পারেন) np.uint8

chunked_hdf.pyসৌন্দর্য এই মত:

import sys
import h5py

def main():
    data = read()

    if sys.argv[1] == 'x':
        x_slice(data)
    elif sys.argv[1] == 'z':
        z_slice(data)

def read():
    f = h5py.File('/tmp/test.hdf5', 'r')
    return f['seismic_volume']

def z_slice(data):
    return data[:,:,0]

def x_slice(data):
    return data[0,:,:]

main()

memmapped_array.pyঅনুরূপ, তবে টুকরোগুলি আসলে মেমরিতে লোড হয় তা নিশ্চিত করার জন্য আরও স্পর্শের জটিলতা রয়েছে (ডিফল্টরূপে, অন্য একটি memmappedঅ্যারে ফিরে আসবে, যা আপেল থেকে আপেলের তুলনা হবে না)।

import numpy as np
import sys

def main():
    data = read()

    if sys.argv[1] == 'x':
        x_slice(data)
    elif sys.argv[1] == 'z':
        z_slice(data)

def read():
    big_binary_filename = '/data/nankai/data/Volumes/kumdep01_flipY.3dv.vol'
    shape = 621, 4991, 2600
    header_len = 3072

    data = np.memmap(filename=big_binary_filename, mode='r', offset=header_len,
                     order='F', shape=shape, dtype=np.uint8)
    return data

def z_slice(data):
    dat = np.empty(data.shape[:2], dtype=data.dtype)
    dat[:] = data[:,:,0]
    return dat

def x_slice(data):
    dat = np.empty(data.shape[1:], dtype=data.dtype)
    dat[:] = data[0,:,:]
    return dat

main()

প্রথমে এইচডিএফের কার্যকারিতাটি একবার দেখে নেওয়া যাক:

jofer at cornbread in ~ 
$ sudo ./clear_cache.sh

jofer at cornbread in ~ 
$ time python chunked_hdf.py z
python chunked_hdf.py z  0.64s user 0.28s system 3% cpu 23.800 total

jofer at cornbread in ~ 
$ sudo ./clear_cache.sh

jofer at cornbread in ~ 
$ time python chunked_hdf.py x
python chunked_hdf.py x  0.12s user 0.30s system 1% cpu 21.856 total

একটি "পূর্ণ" এক্স-স্লাইস এবং একটি "পূর্ণ" জেড-স্লাইস একই পরিমাণে সময় নেয় (~ 20 সেকেন্ড)। এটি একটি 8 গিগাবাইট অ্যারে বিবেচনা করে দেখুন, এটি খুব খারাপ নয়। অধিকাংশ সময়

এবং আমরা যদি এটি স্মরণে থাকা অ্যারের সময়ের সাথে তুলনা করি (এটি ফরট্রান-অর্ডারযুক্ত: একটি "জেড-স্লাইস" সবচেয়ে ভাল কেস এবং "এক্স-স্লাইস" সবচেয়ে খারাপ ক্ষেত্রে case):

jofer at cornbread in ~ 
$ sudo ./clear_cache.sh

jofer at cornbread in ~ 
$ time python memmapped_array.py z
python memmapped_array.py z  0.07s user 0.04s system 28% cpu 0.385 total

jofer at cornbread in ~ 
$ sudo ./clear_cache.sh

jofer at cornbread in ~ 
$ time python memmapped_array.py x
python memmapped_array.py x  2.46s user 37.24s system 0% cpu 3:35:26.85 total

হ্যাঁ, আপনি যে অধিকার পড়া। এক স্লাইস দিকের জন্য 0.3 সেকেন্ড এবং অন্যটির জন্য ~ 3.5 ঘন্টা

"এক্স" দিকের টুকরো টুকরো করার সময় পুরো 8 জিবি অ্যারেটিকে মেমরিতে লোড করতে এবং আমাদের যে স্লাইসটি চেয়েছিল তা নির্বাচন করতে যে পরিমাণ সময় লাগে তার চেয়ে অনেক বেশি সময়! (আবার এটি ফোর্টরান অর্ডারযুক্ত অ্যারে The বিপরীত এক্স / জেড স্লাইস টাইমিংটি সি-অর্ডার করা অ্যারের ক্ষেত্রে হবে the)

তবে, আমরা যদি সর্বদা সেরা-কেস দিকের দিক দিয়ে একটি স্লাইস নিতে চাই, তবে ডিস্কে থাকা বড় বাইনারি অ্যারে খুব ভাল। (~ ০.০ সেকেন্ড!)

একটি স্মরণকৃত অ্যারে সহ, আপনি এই আই / ও বিযুক্তির সাথে আটকে আছেন (বা সম্ভবত অ্যানিসোট্রপি আরও ভাল শব্দ)। যাইহোক, একটি জঞ্জাল এইচডিএফ ডেটাসেটের সাহায্যে আপনি পছন্দগুলি বেছে নিতে পারেন যে অ্যাক্সেস হয় সমান বা নির্দিষ্ট ব্যবহারের ক্ষেত্রে অনুকূলিত। এটি আপনাকে আরও অনেক নমনীয়তা দেয়।

সংক্ষেপে

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

সামগ্রিকভাবে, এটি ব্যবহার করে দেখুন এবং দেখুন এটি আপনার ব্যবহারের ক্ষেত্রে ভাল কাজ করে। আমি ভাবছি আপনি অবাক হতে পারেন।


4
দুর্দান্ত উত্তর। আমি যুক্ত করতে চাই যে আপনি আপনার চুনক লেআউটটিকে আপনার সাধারণ ডেটা অ্যাক্সেস প্যাটার্নে কাস্টমাইজ করতে পারেন। আপনার যদি অ্যাক্সেস প্যাটার্নটির মোটামুটি অনুমানযোগ্য স্টেনসিল আকার থাকে তবে আপনি সাধারণত আপনার ছাঁটাই বেছে নিতে পারেন যেমন সর্বদা অনুকূল গতির কাছাকাছি অর্জন করতে।
ইলকো হুগেনডোর্ন 20

4
দুর্দান্ত উত্তর! এক জিনিস যা ছোঁড়ার বিষয়ে উল্লেখ করা হয়নি তা হ'ল খণ্ড ক্যাশের প্রভাব। প্রতিটি ওপেন ডেটাসেটের নিজস্ব খণ্ড ক্যাশে থাকে, যার ডিফল্ট আকার 1 এমবি হয়, যা সি 5 এ H5Pset_chunk_cache () ব্যবহার করে সামঞ্জস্য করা যায় এটি আপনার অ্যাক্সেসের নিদর্শনগুলির কথা চিন্তা করার সময় সাধারণত কতগুলি অংশ মেমরিতে রাখা যায় তা বিবেচনা করা কার্যকর। যদি আপনার ক্যাশে ধরে রাখতে পারে, বলুন, 8 টি অংশ এবং আপনার ডেটাসেটটি স্ক্যানের দিকে 10 টি অংশ আছে, আপনি প্রচুর ছোঁড়াবেন এবং অভিনয়টি ভয়ানক হবে।
ডানা রবিনসন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.