есть такая практическая заморочка. Допустим имеется файл на 30 гект. Нужно чтать его с интерливом по схеме [block0][block30][block60]... [block1][block31][block61]... ...... Это потому что памяти только 1Г =((( Опыт показывает, что скипуя таким образом скорость чтения снижается с 50 метров за секунду аж до 3 метров-в-секунду ... Вроде считываем те же 30 Г но тока за 5 часов=((( Толи кеш у винта виноват толи сик головок... Как с энтим можно бороться, такие мысли: 1) попробовать транспонировать филес чтобы читать блоки подряд, но это требует места и времени. Изза фрагментации диска не факт что новые блоки ляжут хорошо, тем более что придется писать в несколько потоков. 2) твердотелый винт? Не факт опять, у него тоже есть кеш наверняка 3) Thread Building Block - не знаю что это такое 4) какие нить winapi? Я пока только из языка высокого уровня умею файлы читать...
TSS, посмотрел в Вики про TBB. Это чтото для многопроцессорности и не ясно как оно может помочь, да и сложно для таких чайников как я
Спасибо за наводку. Попробовал FILE_FLAG_RANDOM_ACCESS... Никакого эффекта на скорость чтения не обнаружил. Вообще, флаг рекомендательный, если винда видит что файл дергают туда-сюда она сама может подстроить стратегию использования буфера? FILE_FLAG_NO_BUFFERING - это очень суровый флаг. Требует сначала определить размер сектора устройства, скажем 512 байт, потом выделить буфер по адресу кратному этому сектору и читать строго целое их число... Это жестоко Глянуть можно, но мне нужна целая лекция, для чего сия функция нужна и как ее использовать. Подробный рассказ. Не отрицаю, что вам это расписывать к примеру западло. Ну может кому другому не влом будет
Навскидку, случайная ссылка из Гугла: http://www.developing.ru/com/memory_mapped_files_01.html А вообще, почитайте уже Рихтера, раз под win32 пишете. Полезно.
persicum Без конкретизации алгоритма ничего толком не скажешь. Если алгоритм допускает блочную обработку, то ес-но ее и нужно использовать, т.е. ситывать сразу большие последовательные куски из файла и уже в памяти обрабатывать блоки в нужном порядке. При такой блочной обработке способ чтения блока особой роли не играет - можно и через ReadFile и через FileMapping. Но юзание Filemapping-а в лоб, т.е. сначала 0,30,60.. по всему файлу, затем 1,31,61... по всему файлу - ес-но ничего не даст
Пришла в голову дурацкая мысль... persicum, ты, наверное, используешь единственный файловый хэндл для чтения? Попробуй открыть N хэндлов, перемотай их, соответственно, на 0, 30, 60 и т. д. блок и поочередно читай из хэндлов последовательно. Интересно, как при этом изменится скорость?
ava Гы-Гы :+)) persicum Действительно leo прав - дело не в способе чтения, а в том что считываешь ты не 30Г а во много раз больше... "Виноват" конечно кэш, точнее несоответствие схем работы кэша и программы. Данные читаются блоками кратными одному или нескольким кластерам диска, но используется только их маленькая часть, а к тому времени как они опять понадобятся они давно вытеснены из кэша и опять читаются с диска. Можно попробовать прикрутить "своё кэширование", т.е. при первом заходе из каждого блока копируешь в памяти "подблок", так чтобы общее количество этих подблоков полностью умещалось в свободное ОЗУ (т.е. составляло 500-700М при 1Г общей памяти, иначе будет тормозить файл подкачки). Дальше работаешь с этими подблоками по своей схеме пока они не кончатся, и опять прогоняешь весь файл считывая очередную их партию. Конечно от замедления связанного с многократным считыванием файла ты не избавишься, но хотябы этот процесс можно сделать подконтрольным и выжать максимум не зависящий от особенностей чтения файла осью.
Проблема в том, что функционально связаны как раз блоки 1,30,60, но никак не блоки 1 и 2... У кого-нить есть винт Solid State или RAM-диск на материнке тоже технологии SSD?
persicum Если расстояние между блоками меньше кластера диска (или той единицы чтения на которую расчитана используемая функция чтения), то ты полюбому пробежав по цепочке 1,30,60,... прочитаешь его весь. Но объём кэш не позволит тебе сохранить результаты чтения и в цепочке 2, 31, 61,... тебе опять придётся его читать. Я предлагаю частичное решение - во время прочтения 1,30,60, одновременно запоминать в ОЗУ буфере блоки 2, 31, 61,... 3,32,62... и т.д. насколько хватит свободного ОЗУ. А при втором, третьем и т.д. заходе уже брать их из этого буфера пока он не кончится. Понятно что все 29 цепочек сразу запомнить не получится, но даже если памяти хватит только на одну следющую цепочку получишь удвоение скрости за счёт того, что будешь читать 30Гб с диска не 30, а только 15раз. Кстати похоже в этом случае и разумное использование файла подкачки может оказаться вполне оправданным - он же как правило мало фрагментирован и будет работать быстрее лишнего пробега по файлу, особенно с учётом "плотного" размещения в нём блоков. Т.е. даже если 1/30 (2х ускорение) или 1/15 (4х ускорение) часть файла не помещается в свобдное ОЗУ, не заморачиваться на этом факте, а поручать системе использовать подкачку будет вполне приёмлимо.
persicum Это не проблема. Проблема в том, что ты с этими блоками делаешь. Например, если по этим блокам считать какой-то хэш, сумму, макс\мин и т.д. и т.п., или любые другие действия в результате которых для для хранения промежуточных рез-тов требуется много меньше памяти, чем суммарный размер этих блоков, то проблемы собс-но и нет. Просто вместо обработки одной серии блоков нужно "параллельно" выполнять и копить рез-ты обработки 29 серий
Согласен, целью такого "противоестественного" чтения является собрать все нужные данные чтобы сразу вычислить функцию за один раз вместо того чтобы вычислять одновременно 30 функций но с частичным набором данных, что еще требует сильно голову поломать как это можно сделать. А что тут такого? Ведь это гораздо проще. Это все винт виноват как механическое устройство хотя и с произвольным доступом, но на самом деле любящим чтобы с него читали только подряд. Я же не прошу его терабайт считывать, я только хочу с него 30 гигов считать, а он зараза считывает 30 раз по 30. Буду смотреть в сторону SSD, может поможет.
Почему нет? Это же один простой цыкл. В файл, кстати, можно писать "с дырками" - наверное лучше MemoryMapped - если сразу "дать понять" планировщику что файл будет "очень большой" записав последний блок - может он разбереццо как лучше распределить файл на винте.
Винту пофиг чего и как читать. Но у него как у механического устройства есть принципиальные механические ограничения, обойти которые каким-то чудесным образом просто невозможно. Из-за принципиальных физ.ограничений современные диски и ОЗУ не сильно отличаются по скорости\латентности произвольного доступа от своих собратьев 10-летней давности. Для дисков это ограничение на скорость вращения 7600 или 10000 об/мин и на время перемещения головок ~8-10мс, а для ОЗУ это задержка переключения вентилей ~4-7 нс. Поэтому все современные "заоблачные" скорости чтения\записи и HDD и особенно ОЗУ достигаются только при последовательном доступе и обязаны специальным ухищрениями - в HDD чтением за один раз целиком всей дорожки, а в ОЗУ чтением всей строки матрицы RAM с последующей передачей прочитанных данных на "офигенной" скорости, во много-много раз первышающей скорость произвольного\первоначального доступа. Поэтому нужно не "бицца качаном ап стену", требуя от HDD и DRAM невозможного, а сказать спасибо гению инженерной мысли за то, что несмотря на физ.ограничения удалось хотя бы для последовательного доступа повысить скорость чиения\записи на порядок с лишним. Резюме: современные устройства с произвольным доступом не гарантируют того, что скорость произвольноо и последовательного доступа будет одинаковой, хочешь непременно произвольный - получи свои ~3Mb/s и не вякай