Параллельная запись в несколько (десятков) файлов

Тема в разделе "WASM.WIN32", создана пользователем _DEN_, 13 май 2010.

  1. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Есть несколько (десятков) независимых параллельних потоков. Каждый из них принимает по сети данные блоками от нескольких сот байт до нескольких десятков килобайт, и сразу же пишет эти блоки в свой файл на винт. То есть 16 потоков = 16 сетевых соединений + 16 файлов. На деле эти данные - это видео-фреймы, частота блоков - 30 шт. в секунду. С точки зрения кода для каждого блока я делаю запись в файл через std::ofstream::write, что, вероятно, в итоге эквивалентно WriteFile(Ex).

    Практика показала, что такая вот запись "в лоб" не оптимальна - пара десятков потоков дают достаточно большую нагрузку, которая заметно больше, чем аналогичная функциональность у сторонних приложений.

    Как бы вы посоветовали это оптимизировать?
     
  2. assasincore

    assasincore New Member

    Публикаций:
    0
    Регистрация:
    7 апр 2010
    Сообщения:
    55
    Selectors, APC thread, WriteFileEx, ReadFileEx, WSASend, WSARecv, + google
     
  3. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    assasincore

    Еще ты забыл МЧС, МПС и МТС.


    Добавлю, что хочется решения на уровне алгоритма, без диких платформных хаков, чтобы уложиться в stl + boost.
     
  4. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Имхо иммет смысл организовать очередь записи чтобы поток не пытался писать на диск до тех пор пока предидущий по очереди не закончит (пусть пока копит данные в памяти).

    У винды тоже есть такая проблема - попробуй одновременно запустить на параллельное копирование два больших файла или два каталога с кучами файлов - тормоза будут дикие -раз в 5-10 медленнее чем дождаться завершения копирования одного а затем копировать второй, но win этого сама сообразить не может и тупо конкурирует сама с собой :) Особенно сильно это при копировании с участием флешки видно.
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Да винда отстой, линукс почти всю память под файловый кэш пользует.
     
  6. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Y_Mur
    Booster
    Ребята, все это конечно здорово, но:

    _DEN_
    Как-то я совсем забыл про Boost.Asio.
     
  7. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Думаю попробовать следующее: во-первых - использовать асинхронную запись на Boost.Asio, во-второых - сделать небольшую буфферизацию в клиентском коде, чтобы апи не дергалось из-за каждых ста байт, а, скажем данные уходили в WriteFile (или что там) блоками по несколько сот килобайт. Ну или мегабайт.
     
  8. MikDay

    MikDay New Member

    Публикаций:
    0
    Регистрация:
    5 май 2005
    Сообщения:
    32
    Адрес:
    Minsk
    _DEN_
    что, вероятно, в итоге эквивалентно WriteFile(Ex)

    Между WriteFileEx и WriteFile есть существенная разница - WriteFileEx всегда ассинхронна и, если кэша не хватает, может начать гонять головки винчестера.
     
  9. assasincore

    assasincore New Member

    Публикаций:
    0
    Регистрация:
    7 апр 2010
    Сообщения:
    55
    Какие хаки?
    WASM.WIN32 - причем здесь stl + boost ? Эти библиотеки изначально быстро работать не могут ...

    Точно...

    Так как WriteFile враппер для WriteFileEx, и вызов будет зависить от OVERLAPPED, либо будет дожидаться hFile, либо нет....
     
  10. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    _DEN_
    Boost.Asio конечно попробуй возможно и поможет, но оно тоже в итоге упрётся в то как это реализовано в дебрях win. А win тормозит при попытке писать параллельно и при записи мелких и при записи крупных блоков ;)

    А откуда известно что у этих сторонних приложений не приняты меры предотваращющие параллельную запись по иннициативе приложения?
     
  11. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    assasincore
    Бугага. Спасибо, можешь не продолжать.

    Y_Mur
    Этого, конечно же, не известно. Я имел ввиду аналогичная с точки зрения пользователя - N потоков одновременно пишутся на винт. А как они там пишутся - паралельно, последовательно, синронно, асинхронно - это, конечно, юзеру пофиг. Главное что работает, и удовлетворяет его, тобишь юзерским, требованиям.

    Пока что вижу три возможных решения: 1) на каждый поток свой boost.asio event loop, 2) один event loop на всех с разрешением писать паралельно несколько файлов, и 3) один event loop на всех, одновременно пишущий не более одного файла. Правда не уверен, есть ли смысл с точки зрения WinAPI в boost.asio event loop-е при работе с файлами.

    Думаю тут главный вопрос в том, можно ли винде доверять сериализацию записи, или это лучше делать самому.
     
  12. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    _DEN_
    Может стоит запись вести в одном потоке? 16 потоков принимают 17 пишет.
    А во вторых зачем тебе 16 потоков сделай все в одном, на асинхронных сокетах.
     
  13. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Pavia

    Ну второй и третий вариант постом выше как раз и подразумевает запись в одном потоке.

    Да блин, ну конечно же сделал бы, если бы была такая возможность :) Синхронную работу с сетью навязывает сторонняя библиотека, через которую приходится работать. Переписывать библиотеку - не вариант.
     
  14. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Конечно лучше попробовать и сравнить, но мой прогноз что своя сериализация будет работать значительно быстрее виндовой которая работает весьма странно ;).
    Синхронная и асинхронная запись в винде отличаются только режимом ожидания результата операции из записывающего потока. К многопоточной и многозадачной сериализации записи эта асинхронность никакого отношения не имеет.
     
  15. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    http://evgeny-lazin.blogspot.com/2008/12/boostasio.html
     
  16. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Ой, Дэн уже вспомнил )
     
  17. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Y_Mur

    Думаешь что достаточно просто сделать свою сериализацию, и можно не заморачиваться на асинхронные операции?
     
  18. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Асинхронная запись придумана как раз для твоего варианта 1, когда каждый поток сам пишет свои данные и при этом должен быть свободен для приёма новых видеофреймов, а не простаивать ожидая пока завершится запись.

    3й вариант с очередью записи уже предполагает что запись синхронная, т.е. всё равно нужно дожидаться завершения предидущей. Поскольку время, нужное на анализ данных подготовленных принимающими фреймы потоками (т.е. на логику построения очереди) пренебрежимо мало по сравнению с записью очередого буфера на диск то никакого смысла параллелить эти действия не вижу и тогда правильная сериализация при применении синхронных функций получится сама :)

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

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Имхо вводить дополнительный поток для записи не стоит (поскольку это потянет за собой тщательное продумывание механизма передачи данных в него и логики построения очереди) - достаточно завести общую переменную в которой хранится номер потока для которого разрешена запись.
    Обнаружив там свой номер очередной поток записывает на диск то что он принял, и по завершению записи ставит туда номер следующего потока. Возможно здесь потребуется дополнительная логика чтобы записи не были слишком частыми или слишком редкими, но она полюбому проще логики сбора данных дополнительным потоком.
    Асинхронность записи в этом случае очень желательна чтобы не было конфликтов: очередной видеофрейм готов, а поток не может его принять, потому как ждёт завершения записи.
     
  20. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Нагрузка больше функциональности?