При записи большого массива непосредственно на диск в MATLAB есть ли необходимость в предварительном выделении?

Мне нужно написать массив, который слишком велик, чтобы поместиться в памяти .двоичный файл мат. Это можно сделать с помощью matfile функция, которая позволяет произвольный доступ к a .mat файл на диске.

обычно принято советовать предварительно распределять массивы, потому что расширение их на каждой итерации цикла происходит медленно. Однако, когда я был спрашивают, как это сделать, мне пришло в голову, что это может быть не очень хороший совет при записи на диск, а не БАРАН.

будет такая же производительность хит от растет массив применить и если Итак:значительное, когда по сравнению со временем записи на диск в любом случае?

(предположим, что весь файл будет записан в один сеанс!--12-->, поэтому риск серьезной фрагментации файла низкий.)

4 ответов


Q: будет ли применяться тот же показатель производительности от увеличения массива, и если да, то будет ли он значительным по сравнению с временем, которое требуется для записи на диск?

A: да, производительность пострадает, если вы значительно увеличите файл на диске без предварительного выделения. Удар по производительности будет следствием фрагментации. Как вы уже упоминали, фрагментация меньше риска, если файл записывается за один сеанс, но вызовет проблемы, если файл растет значительно.

A вопрос был поднят на веб-сайте MathWorks, и принятым ответом было предварительное выделение, когда это возможно.

Если вы не предварительно выделяете, то степень ваших проблем с производительностью будет зависеть от:

  • ваша файловая система (как хранятся данные на диске, размер кластера),
  • ваше оборудование (HDD время поиска или SSD время доступа),
  • размер вашего файла mat (перемещается ли он в несмежное пространство),
  • и текущее состояние вашего хранилища (существующая фрагментация / свободное пространство).

давайте притворимся, что вы используете недавнюю ОС Windows, и поэтому используете файловая система NTFS. Предположим далее, что он был настроен с размером кластера по умолчанию 4 КБ. Итак, пространство на диске выделяется в 4 блоков КБ и местоположения этих файлов индексируются в таблицу Master File. Если файл растет и непрерывное пространство недоступно, тогда есть только два варианта:

  1. перепишите весь файл на новую часть диска, где достаточно свободного места.
  2. Фрагментируйте файл, сохраняя дополнительные данные в другом физическом месте на диске.

файловая система выбирает наименее плохой вариант, #2, и обновляет запись MFT, чтобы указать, где новые кластеры будут на диске.

Illustration of fragmented file on NTFS, from WindowsITPro

теперь жесткий диск должен физически перемещать головку чтения для чтения или записи новых кластеров, и это (относительно) медленный процесс. С точки зрения перемещения головы и ожидания правильной области диска, чтобы вращаться под ней ... вы, вероятно, будете смотреть на время поиска о 10мс. Таким образом, каждый раз, когда вы нажмете фрагмент, будет дополнительная задержка 10 мс, пока HDD перемещается для доступа к новым данным. SSD имеют гораздо более короткие времена поиска (отсутствие двигающих частей). Для простоты мы игнорируем мульти-тарелочке системы и RAID-массивы!

Если вы продолжаете расти файл в разное время, то вы можете испытать много фрагментации. Это действительно зависит от того, когда / сколько файл растет, а как еще вы используете жесткий диск. Производительность, которую вы испытываете, также будет зависеть от того, как часто Вы читаете файл и как часто вы сталкиваетесь с фрагментарный.

MATLAB хранит данные в колонка-главный заказ, и из комментариев кажется, что вы заинтересованы в выполнении операций по столбцам (суммы, средние) для набора данных. Если столбцы становятся несмежными на диске, то вы собираетесь ударить много фрагментов на каждой операции!

Как уже упоминалось в комментариях, действия чтения и записи будут выполняться через буфер. Как @user3666197 указывает на ОС спекулятивно чтения впереди текущие данные на диске, на том основании, что вы, вероятно, захотите, чтобы эти данные были следующими. Такое поведение особенно полезно, если жесткий диск будет время от времени простаивать - поддержание его работы на максимальной емкости и работа с небольшими частями данных в буферной памяти может значительно повысить производительность чтения и записи. Однако из вашего вопроса звучит так, как будто вы хотите выполнять большие операции на огромном (слишком большом для памяти) .файл мат. Учитывая ваш случай, то жесткий диск будет работать на емкость в любом случае, и файл данных слишком велик, чтобы поместиться в буфер, поэтому эти конкретные трюки не решат вашу проблему.

Так ...Да, ты!--50-->должны предварительно выделить. Да, будет применяться хит производительности от увеличения массива на диске. Да, это, вероятно, будет значительным (это зависит от таких особенностей, как объем роста, фрагментация и т. д.). И если ты собираешься ... --50-->действительно попасть в КВД дух тогда все, что ты делаешь, выбросьте MATLAB, shard ваши данные и попробуйте что-то вроде Apache Spark! Но это уже другая история.

Это ответ на твой вопрос?

П. С. поправки / поправки приветствуются! Я был воспитан на POSIX inodes, поэтому искренние извинения, если здесь есть какие-либо неточности...


предварительное распределение переменной в ОЗУ и предварительное распределение на диске не решают ту же проблему.

в оперативной памяти

чтобы развернуть матрицу в ОЗУ, MATLAB создает новую матрицу с новым размером и копирует значения старой матрицы в новую и удаляет старую. Это стоит большой производительности.

если вы предварительно распределили матрицу, размер ее не изменяется. Таким образом, у MATLAB больше нет причин для копирования этой матрицы больше.

на жесткий диск

проблема, на жестком диске разрозненность как сказал Гномедеплюм. Фрагментация по-прежнему будет проблемой, даже если файл записывается за один сеанс.

вот почему: жесткий диск, как правило, будет немного фрагментирован. Представьте

  • # быть блоками памяти на жестком диске, которые заполнены
  • M быть блоками памяти на жестком диске, которые будут используется для сохранения данных вашей матрицы
  • - чтобы быть свободными блоками памяти на жестком диске

теперь жесткий диск может выглядеть так, прежде чем вы напишете на него матрицу:

###--##----#--#---#--------------------##-#---------#---#----#------

когда вы пишете части матрицы (например,MMM блоки) вы можете себе представить процесс, чтобы выглядеть так >!(Я приведу пример, когда файловая система будет просто идти слева направо и использовать первое свободное пространство, которое достаточно велико - реальные файловые системы разные):

  1. первая часть Матрицы:
    ###--##MMM-#--#---#--------------------##-#---------#---#----#------
  2. вторая часть Матрицы: ###--##MMM-#--#MMM#--------------------##-#---------#---#----#------
  3. третья часть Матрицы: ###--##MMM-#--#MMM#MMM-----------------##-#---------#---#----#------
  4. и так далее ...

очевидно, что файл матрицы на жестком диске фрагментирован, хотя мы написали его, не делая ничего другого в то же время.

это может быть лучше, если файл Матрицы был предварительно распределен. Другими словами, мы сообщаем файловой системе, насколько большим будет наш файл, или в этом примере, сколько блоков памяти, мы хотим зарезервировать для него.

представьте, что Матрице нужно 12 блоков:MMMMMMMMMMMM. Мы говорим файловой системе, что нам нужно так много, предварительно распределяя, и она постарается удовлетворить наши потребности как можно лучше. В этом примере нам повезло: есть свободное пространство с >= 12 блоками памяти.

  1. предварительное распределение (нам нужно 12 блоков памяти):
    ###--##----#--#---# (------------) --------##-#---------#---#----#------
    Файловая система резервирует пространство между скобками для наших матрицу и напишу туда.
  2. первая часть Матрицы:
    ###--##----#--#---# (MMM---------) --------##-#---------#---#----#------
  3. вторая часть Матрицы:
    ###--##----#--#---# (MMMMMM------) --------##-#---------#---#----#------
  4. третья часть Матрицы:
    ###--##----#--#---# (MMMMMMMMM---) --------##-#---------#---#----#------
  5. четвертая и последняя часть Матрицы:
    ###--##----#--#---# (MMMMMMMMMMMM) --------##-#---------#---#----#------

вуаля, нет фрагментации!


аналогия

обычно вы можете представить себе этот процесс как покупку билетов в кино для большой группы. Вы хотели бы придерживаться вместе, как группа, но уже есть места в театре, зарезервированные другими людьми. Чтобы кассир мог удовлетворить ваш запрос (большая группа хочет держаться вместе), ему/ей нужны знания о том, насколько велика ваша группа (предварительное распределение).


A быстрый ответ ко всему обсуждению (в случае, если у вас нет времени следить или технического понимания):

  • предварительное выделение в Matlab актуально для операций в ОЗУ. Matlab не дает низкоуровневого доступа к операциям ввода-вывода, и поэтому мы не может поговорим о предварительном выделении чего-то на диске.
  • при записи большого количества данных на диск, было замечено, что чем меньше пишет, тем быстрее выполнение задачи и меньше-это фрагментация на диске.

таким образом, если вы не можете написать за один раз, разделить записи на большие куски.


Пролог

этот ответ основан как на исходном сообщении, так и на разъяснениях (оба ) предоставлены автором в течение последней недели.

вопрос о негативных производительности(s) ввел низкоуровневый, физическ-средств-зависимый,"фрагментации", введенный обоими слоями файловой системы и доступа к файлам дополнительно сталкиваясь оба в значениях TimeDOMAIN и в ComputingDOMAIN повторяемость этих С проблемами реального использования такого подхода.

наконец-то государство-оф-арт было предложено принципиально быстрое решение данной задачи, чтобы минимизировать ущерб как от напрасных усилий, так и от ошибок неправильной интерпретации из идеализированных или иным образом недействительных предположений, так что риск "серьезной фрагментации файла низок" из-за предположения, что весь файл будет написано за один сеанс (что просто принципиально не возможно во время многих многоядерных / многопроцессорных операций современных O / S в режиме реального времени в течение времени создания и последовательности обширных модификаций(ов) ( ref. ограничения размера MATLAB) файла (объектов) BLOB размером с TB внутри современных файловых систем COTS ).


можно ненавидеть факты, однако факты остаются верными, пока не будет двигаться более быстрый и лучший метод в


во-первых, прежде чем рассматривать производительность, осознавать пробелы в концепции

  1. реальная производительность неблагоприятный удар не причинил по HDD-IO или связанные с фрагментацией файла

  2. ОЗУ не альтернатива для полупостоянного хранения .mat

  3. дополнительные пределы операционной системы и мероприятия + дополнительные драйверы и аппаратные абстракции были проигнорированы из предположений о неизбежных накладных расходах
  4. указанная вычислительная схема была опущена из обзора того, что будет иметь наибольшее влияние / влияние на результативность

дано:

  • вся обработка предназначена для запустить только один раз, нет оптимизации / итерации, без непрерывной обработки

  • данные 1E6 double Float-значения x 1E5 столбцы = о 0.8 TB (+HDF5 накладные)

  • несмотря на оригинальный пост, там нет случайных IO связанные с обработкой

  • сведения приобретение фаза связывается с .NET для получения DataELEMENTs в MATLAB

    это означает, что с v7.4,

    a 1.6 GB limit on рабочее пространство MATLAB в 32bit Win (2.7 GB с переключателем 3GB )

    a 1.1 GB limit on самая большая матрица MATLAB в wXP / 1.4 GB wV / 1.5 GB

    немного "отпустили" 2.6 GB limit на Matlab WorkSpace + ограничение 2.3 GB на самую большую матрицу в 32-битном Linux O / S.

    имея 64bit O / S не поможет никакая реализация 32bit MATLAB 7.4 и не будет работать из-за другой предел, максимальное количество ячеек в массиве, которое не будет покрывать 1e12, запрошенное здесь.

    единственный шанс-это иметь и

  • сведения для хранения фаза предполагает блок-Запись упорядоченных по строкам блоков данных (набор упорядоченных по строкам блоков данных ) в MAT-file на HDD-устройстве

  • сведения обработка этап предполагает повторную обработку данных в MAT-file на HDD-устройстве после того, как все входы были приобретены и маршалированы на файловое хранилище вне ОЗУ, но в порядке столбцов

  • просто столбец-мудрый mean() - s/max() - es необходимы для расчета ( ничего более сложного )

факты:

  • MATLAB использует "ограниченную" реализацию HDF5 файловая структура для двоичных файлов.

обзор измерений производительности на реальных данных & real-hardware (HDD + SSD), чтобы получить ощущение масштабов неизбежных их слабостей

Иерархический Формат Данных (HDF) родился в 1987 году в Национальном центре суперкомпьютерных приложения (NCSA), около 20 лет назад. Да, такой старый. Цель состояла в том, чтобы разработать формат файла, объединяющий гибкость и эффективность бороться с чрезвычайно большой набор данных. Каким-то образом файл HDF не использовался в мейнстриме, поскольку только несколько отраслей действительно смогли действительно использовать его ужасающей мощности или просто не нуждаетесь в них.

гибкость означает, что файловая структура несет некоторые накладные расходы, не нужно использовать, если содержимое массива не изменяется (вы оплатить стоимость не потребляя никакой пользы от его использования ) и предположение, что HDF5 ограничения на общий размер из данных он может содержать своего рода помощь и сохраняет сторону MATLAB проблемы не правильно.

MAT-files хороши в принципе, так как они избегают в противном случае постоянной необходимости загружать весь файл в ОЗУ, чтобы иметь возможность работать с ним.

тем не менее MAT-files не служат хорошо простую задачу, как было определено и разъяснено здесь. Попытка сделать это приведет только к низкой производительности и фрагментации файла HDD-IO ( добавление нескольких десятков миллисекунд во время write-through - s и что-то меньшее, чем это на read-ahead - s во время расчетов ) не поможет вообще в оценке основной причины общей низкой производительности.


профессиональный подход к решению

вместо того, чтобы перемещать весь гигантский набор 1E12 DataELEMENTs в массив данных прокси-сервера MATLAB в памяти, который только что запланирован для следующего последовательного потока HDF5 / MAT-file HDD-устройство IO - s (write-throughS и O/S против аппаратно-цепной конфликт / суб-оптимизированный read-aheads), чтобы все immenses работали "просто [женаты] готовы" для нескольких и тривиально простых вызовов mean() / max() функции MATLAB( которые сделают все возможное, чтобы обновить каждый из 1E12 DataELEMENTs в другом порядке ( и даже дважды -- да -- еще один цирк сразу после первой работы-обработка кошмар получает все путь вниз, через все узкие места HDD-IO) обратно в MATLAB in-RAM-objects,сделать редизайн этот шаг в трубопроводную обработку BigDATA с самого начала.

while true                                          % ref. comment Simon W Oct 1 at 11:29
   [ isStillProcessingDotNET,   ...                 %      a FLAG from .NET reader function
     aDotNET_RowOfVALUEs ...                        %      a ROW  from .NET reader function
     ] = GetDataFromDotNET( aDtPT )                 %                  .NET reader
   if ( isStillProcessingDotNET )                   % Yes, more rows are still to come ...
      aRowCOUNT = aRowCOUNT + 1;                    %      keep .INC for aRowCOUNT ( mean() )
      for i = 1:size( aDotNET_RowOfVALUEs )(2)      %      stepping across each column
         aValue     = aDotNET_RowOfVALUEs(i);       %      
         anIncrementalSumInCOLUMN(i) = ...
         anIncrementalSumInCOLUMN(i) + aValue;      %      keep .SUM for each column ( mean() )
         if ( aMaxInCOLUMN(i) < aValue )            %      retest for a "max.update()"
              aMaxInCOLUMN(i) = aValue;             %      .STO a just found "new" max
         end
      endfor
      continue                                      %      force re-loop
   else
      break
   endif
end
%-------------------------------------------------------------------------------------------
% FINALLY:
% all results are pre-calculated right at the end of .NET reading phase:
%
% -------------------------------
% BILL OF ALL COMPUTATIONAL COSTS ( for given scales of 1E5 columns x 1E6 rows ):
% -------------------------------
% HDD.IO:          **ZERO**
% IN-RAM STORAGE:
%                  Attr Name                       Size                     Bytes  Class
%                  ==== ====                       ====                     =====  =====
%                       aMaxInCOLUMNs              1x100000                800000  double
%                       anIncrementalSumInCOLUMNs  1x100000                800000  double
%                       aRowCOUNT                  1x1                          8  double
%
% DATA PROCESSING:
%
% 1.000.000x .NET row-oriented reads ( same for both the OP and this, smarter BigDATA approach )
%         1x   INT   in aRowCOUNT,                 %%       1E6 .INC-s
%   100.000x FLOATs  in aMaxInCOLUMN[]             %% 1E5 * 1E6 .CMP-s
%   100.000x FLOATs  in anIncrementalSumInCOLUMN[] %% 1E5 * 1E6 .ADD-s
% -----------------
% about 15 sec per COLUMN of 1E6 rows
% -----------------
%                  --> mean()s are anIncrementalSumInCOLUMN./aRowCOUNT
%-------------------------------------------------------------------------------------------
% PIPE-LINE-d processing takes in TimeDOMAIN "nothing" more than the .NET-reader process
%-------------------------------------------------------------------------------------------

код трубопроводD стратегия вычисления BigDATA будет умным способом в основном избегайте промежуточная буферизация хранилища в MATLAB, поскольку она будет постепенно вычислять результаты не более чем примерно 3 x 1E6 ADD/CMP-регистры, все со статической компоновкой,избежать прокси-хранение в HDF5 / MAT-file, абсолютно не все связанные с HDD-IO узкие места и низкие скорости BigData sustained-read-s ' (не говоря уже о промежуточных / BigData sustained-пишет... ) и избежать плохо выполнять памяти использовать только для виду-с подсчета и Макс-Эс.


Эпилог

трубопровод обработка ничего нового под солнцем.

он повторно использует то, что ориентированные на скорость решения HPC уже использовать в течение десятилетий

[ поколения до того, как тег BigDATA был "изобретен" в отделе маркетинга. ]

забудьте о миллиардах операций блокировки HDD-IO и перейдите в распределенное распределенное решение от процесса к процессу.


нет ничего быстрее, чем это


если бы это было, все монстры FX business и HFT Hedge Fund уже были бы там...