Strategi I / O untuk masalah komputasi dengan set data besar?

15

Grup penelitian saya berfokus pada dinamika molekuler, yang jelas dapat menghasilkan gigabytes data sebagai bagian dari lintasan tunggal yang kemudian harus dianalisis.

Beberapa masalah yang kami khawatirkan melibatkan korelasi dalam set data, yang berarti bahwa kita perlu melacak sejumlah besar data dalam memori dan menganalisisnya, daripada menggunakan pendekatan yang lebih berurutan.

Yang ingin saya ketahui adalah strategi apa yang paling efisien untuk menangani I / O set data besar ke dalam skrip. Kami biasanya menggunakan skrip berbasis Python karena membuat pengkodean file I / O jauh lebih tidak menyakitkan daripada C atau Fortran, tetapi ketika kami memiliki puluhan atau ratusan juta baris yang perlu diproses, tidak begitu jelas apa pendekatan terbaiknya. . Haruskah kita mempertimbangkan untuk melakukan input file bagian dari kode dalam C, atau strategi lain yang lebih berguna? (Apakah hanya mem-preloading seluruh array ke dalam memori lebih baik daripada serangkaian pembacaan berurutan "chunks" (urutan megabyte)?

Beberapa catatan tambahan:

  • Kami terutama mencari alat skrip untuk post-processing, daripada alat "on-line" —karena itu penggunaan Python.

  • D=16limΔt(x(t+Δt)x(t))2
aeismail
sumber

Jawaban:

6

Saya berasumsi pertanyaan Anda berasal dari pengamatan bahwa I / O menyebabkan overhead yang signifikan dalam seluruh analisis Anda. Dalam hal ini, Anda dapat mencoba untuk tumpang tindih I / O dengan perhitungan.

Pendekatan yang berhasil tergantung pada bagaimana Anda mengakses data, dan perhitungan yang Anda lakukan pada data itu. Jika Anda dapat mengidentifikasi pola, atau akses ke berbagai wilayah data diketahui sebelumnya, Anda dapat mencoba untuk mengambil "potongan berikutnya" dari data di latar belakang saat memproses "potongan saat ini".

Sebagai contoh sederhana, jika Anda hanya menelusuri file sekali dan memproses setiap baris atau kumpulan baris, Anda dapat membagi aliran dalam potongan baris (atau MB). Kemudian, pada setiap iterasi di atas chunk, Anda dapat memuat chunk i +1 saat memproses chunk i.

Situasi Anda mungkin lebih kompleks dan membutuhkan lebih banyak solusi yang terlibat. Bagaimanapun, idenya adalah untuk melakukan I / O di latar belakang sementara prosesor memiliki beberapa data untuk dikerjakan. Jika Anda memberikan detail lebih lanjut tentang masalah spesifik Anda, kami mungkin dapat memeriksanya lebih dalam;)

---- Versi diperpanjang setelah memberikan rincian lebih lanjut ----

Saya tidak yakin saya mengerti notasinya, tetapi yah, seperti yang Anda katakan, idenya adalah interaksi semua-untuk-semua. Anda juga menyebutkan bahwa data mungkin sesuai dengan RAM. Kemudian, saya akan mulai dengan mengukur waktu untuk memuat semua data dan waktu untuk melakukan perhitungan. Sekarang,

  • jika persentase I / O rendah (serendah Anda tidak peduli dengan overhead, apa pun itu: 0,5%, 2%, 5%, ...), maka gunakan saja pendekatan sederhana: memuat data sekaligus, dan hitung. Anda akan menghemat waktu untuk aspek penelitian yang lebih menarik.

  • jika Anda tidak mampu membayar biaya overhead, Anda mungkin ingin melihat apa yang disarankan Pedro. Ingatlah apa yang disebutkan Aron Ahmadia, dan ujilah sebelum melanjutkan untuk implementasi penuh.

  • jika sebelumnya tidak memuaskan, saya akan pergi untuk implementasi out-of-core [1]. Karena tampaknya Anda melakukan perhitungan pada data , ada harapan :) Beberapa pseudocode (dengan asumsi hasil analisis Anda sesuai dengan RAM):n2n

    memuat chunk1 dan chunk2
    untuk potongan i = 1 hingga n
        secara asinkron memuat chunk i +1
        untuk potongan di j = i +1 ke n
            secara asinkron memuat chunk j +1
            hitung dengan potongan i, j (* untuk iterasi pertama, ini adalah potongan preloaded 1 dan 2 *)

Catatan: ini adalah kodesemu cepat dan kotor, kita harus menyesuaikan indeks.

Untuk mengimplementasikan ini, adalah umum untuk menggunakan yang disebut double-buffering . Secara kasar: bagi memori dalam dua ruang kerja; saat data dimuat di latar belakang ke dalam ruang kerja 1, prosesor menghitung dengan data di ruang kerja 2. Pada setiap iterasi, tukar peran.

Maaf saya tidak bisa membuat referensi yang bagus saat ini.

[1] Algoritma out-of-core menggabungkan beberapa mekanisme untuk (efisien) menangani data yang berada di disk. Mereka disebut out-of-core sebagai lawan in-core ("in-RAM").

Diego
sumber
7

Saya harus berurusan dengan masalah yang sama sebelumnya, dan solusi favorit saya adalah menggunakan Memory I / O yang dipetakan , meskipun di C ...

Prinsip di baliknya cukup sederhana: alih-alih membuka file dan membaca darinya, Anda memuatnya langsung ke memori dan mengaksesnya seolah-olah itu adalah array yang sangat besar. Trik yang membuatnya efisien adalah bahwa sistem operasi tidak benar-benar memuat file , itu hanya memperlakukannya seperti kehabisan memori yang perlu dimuat. Ketika Anda mengakses byte yang diberikan dalam file Anda, halaman memori untuk bagian file tersebut ditukar ke dalam memori. Jika Anda terus mengakses bagian file yang berbeda dan memori menjadi kencang, bagian yang jarang digunakan akan ditukar kembali - secara otomatis!

Pencarian Google yang cepat memberi tahu saya bahwa ini juga tersedia untuk Python: 16.7. mmap - Dukungan file yang dipetakan memori , tapi saya tidak cukup tahu tentang Python untuk mengetahui apakah itu benar-benar hal yang sama.

Pedro
sumber
1
Pastikan Anda mengukur dan menguji sebelum menerapkan sesuatu seperti mmapke dalam kode utama Anda. Banyak sistem operasi modern memberikan kinerja serupa antara reguler readdengan komplikasi yang lebih sedikit. (Juga, ya, mmap di Python menyediakan antarmuka portabel ke peta memori Windows dan UNIX).
Aron Ahmadia
1

Mungkin Anda dapat menggunakan Cython di bagian I / O file Anda dan mengubah bagian ini menjadi kode C?

asmatik
sumber