Стратегії вводу / виводу для обчислювальних задач з великими наборами даних?


15

Моя дослідницька група зосереджується на молекулярній динаміці, яка, очевидно, може генерувати гігабайти даних як частину єдиної траєкторії, яку потім необхідно проаналізувати.

Деякі проблеми, з якими ми стикаємося, стосуються кореляцій у наборі даних, а це означає, що нам потрібно відслідковувати велику кількість даних у пам'яті та аналізувати їх, а не використовувати більш послідовний підхід.

Що я хотів би знати, це які найефективніші стратегії обробки вводу / виводу великих наборів даних у сценарії. Ми зазвичай використовуємо сценарії на основі Python, оскільки це робить кодування вводу-виводу файлів набагато менш болісним, ніж C або Fortran, але коли у нас є десятки чи сотні мільйонів рядків, які потрібно обробити, не так зрозуміло, який найкращий підхід . Чи варто розглянути можливість введення файлової частини коду в C, чи інша стратегія є більш корисною? (Чи буде просто попередня завантаження всього масиву в пам'ять кращою, ніж серія послідовних читань "шматок" (порядок мегабайт)?

Деякі додаткові примітки:

  • Ми в першу чергу шукаємо сценарії інструментів для післяобробки, а не "он-лайн" інструменти - отже, використання Python.

  • D=16limΔт(х(т+Δт)-х(т))2

Відповіді:


6

Я припускаю, що ваше запитання випливає із зауваження, що введення / виведення спричиняє значні накладні витрати у вашому аналізі. У цьому випадку можна спробувати перекрити введення / виведення обчисленнями.

Успішний підхід залежить від способу доступу до даних та обчислень, які ви виконуєте на цих даних. Якщо ви можете ідентифікувати шаблон або доступ до різних регіонів відомий заздалегідь, ви можете спробувати попередньо встановити "наступні фрагменти" даних у фоновому режимі під час обробки "поточних фрагментів".

Як простий приклад, якщо ви лише один раз переходите файл і обробляєте кожен рядок або набір рядків, ви можете розділити потік на шматки рядків (або МБ). Потім під час кожної ітерації над шматками ви можете завантажити шматок i + 1 під час обробки шматка i.

Ваша ситуація може бути більш складною і потребує більш залучених рішень. У будь-якому випадку ідея полягає у виконанні вводу / виводу у фоновому режимі, тоді як у процесора є деякі дані, над якими можна працювати. Якщо ви дасте більше детальних даних щодо вашої конкретної проблеми, ми можемо глибше розглянути її;)

---- Розширена версія після детальної інформації ----

Я не впевнений, що розумію позначення, але добре, як ви сказали, ідея - це взаємодія "все до всіх". Ви також згадуєте, що дані можуть вміщуватися в оперативній пам'яті. Тоді я б почав з вимірювання часу для завантаження всіх даних та часу для проведення обчислень. Тепер,

  • якщо відсоток вводу / виводу низький (низький, як у вас не байдуже накладні витрати, що б це не було: 0,5%, 2%, 5%, ...), просто використовуйте простий підхід: завантажуйте дані одразу і обчислити. Ви заощадите час на більш цікаві аспекти ваших досліджень.

  • якщо ви не можете дозволити собі накладні витрати, ви можете розглянути, що запропонував Педро. Майте на увазі те, що згадав Арон Ахмадія, і протестуйте його, перш ніж перейти до повної реалізації.

  • якщо попереднє не буде задовільним, я б пішов на деяку позапрофільну реалізацію [1]. Оскільки здається, що ви виконуєте обчислення на даних, є надія :) Деякі псевдокоди (якщо вважати, що результати вашого аналізу вміщуються в оперативній пам'яті):н2н

    завантажувати шматок1 і шматок2
    для шматок i = 1 до n
        асинхронно завантажують шматок i + 1
        для шматок у j = i + 1 до n
            асинхронне навантаження шматка j + 1
            обчислити шматки i, j (* для першої ітерації, це попередньо завантажені фрагменти 1 і 2 *)

Примітка: це швидкий і брудний псевдокод, потрібно було б скоригувати індекси.

Для цього звичайно використовувати так зване подвійне буферизація . Грубо кажучи: розділіть пам’ять на дві робочі області; поки дані завантажуються у фоновому режимі в робочу область 1, процесор обчислює дані в робочій області 2. Під час кожної ітерації обмінюйтесь роллю.

Вибачте, що зараз не можу прийти до хорошого посилання.

[1] Непрофільний алгоритм містить деякий механізм (ефективно) обробляти дані, що зберігаються на диску. Вони називаються позаядерними на відміну від in-core ("in-RAM").


7

Мені доводилося стикатися з подібними проблемами раніше, і моє улюблене рішення - використовувати вбудований введення / вивід на карту пам'яті , хоча і в C ...

Принцип, що стоїть за ним, досить простий: замість того, щоб відкривати файл і читати з нього, ви завантажуєте його безпосередньо в пам'ять і отримуєте доступ до нього, ніби це величезний масив. Трюк, який робить його ефективним, полягає в тому, що операційна система насправді не завантажує файл , вона просто розглядає його як замінену пам'ять, яку потрібно завантажити. Коли ви отримуєте доступ до будь-якого заданого байту у вашому файлі, сторінка пам'яті для цієї частини файлу поміняється в пам'ять. Якщо ви продовжуєте отримувати доступ до різних частин файлу і пам'ять стає тісною, менш використовувані частини будуть замінені назад - автоматично!

Швидкий пошук Google підказує мені, що це також доступно для Python: 16.7. mmap - Підтримка файлів , орієнтованих на пам'ять , але я не знаю достатньо про Python, щоб сказати, чи це дійсно те саме.


1
Просто переконайтеся, що ви вимірюєте і тестуєте, перш ніж впроваджувати щось mmapу свій основний код. Багато сучасних операційних систем дають аналогічні показники між звичайними readз меншими складностями. (Також так, mmap в Python забезпечує портативний інтерфейс до карт пам'яті Windows та UNIX).
Арон Ахмадія

1

Можливо, ви можете використовувати Cython у розділах вводу / виводу файлів і перетворити цю частину в код C?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.