Скорость обмена: часто чтение из файла против хранения его с использованием динамической памяти - PullRequest
2 голосов
/ 30 марта 2011

Я пишу программу на C, которая включает чтение файла изображения и считывание каждого пикселя изображения только один раз. Так должен ли я прочитать файл один раз с помощью fread () и сохранить его в некоторой динамической переменной (переменной кучи) или свободно использовать fread () для каждого пикселя ?? Изображение будет размером от 1000 * 1000 до 5000 * 5000. Я буду расширять ту же программу в MPI и CUDA. Буду признателен за любые другие предложения. Спасибо.

Ответы [ 8 ]

4 голосов
/ 30 марта 2011

Даже 12-битному цветному ARGB-изображению потребуется около 150 МБ для разрешения 5000 * 5000 пикселей, что вполне соответствует возможностям всех современных ПК и даже многих видеокарт. Если у вас есть такая память, вы должны прочитать ее один раз в динамически распределенном массиве или что-то в этом роде. Это позволит вам читать все изображение в больших блоках ввода-вывода, что быстрее, и использовать прямые операции с памятью (img[1234][4321][RED] = 34), а не усложнять ваш код функциями ввода-вывода.

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

Тем не менее, современные ОС выполняют обширное кэширование и предварительную выборку данных, поэтому использование fread() может быть не намного медленнее. Более того, в современных системах Linux с glibc-2.3 или новее можно дополнительно использовать mmap() для доступа к файлу, даже когда приложение выполняет ввод-вывод со стандартными функциями stdio.

1 голос
/ 31 марта 2011

Зависит от того, какой алгоритм вам нужно обработать. Изображение 5000 * 5000 составляет около 95 Мб. Ничего страшного.

На стороне Gpu вы можете выполнять асинхронную загрузку в память графического процессора в блоке размером около 4–16 МБ для насыщения полосы пропускания

#pseudocode:

 for chunk in fread(4096MB):
     gpu.uploadAsync (chunk) # will not block
 gpu.execute() #wait that all the previous memory transfers are completed.

Вы должны использовать закрепленную память на cuda, и я думаю, что если вы запомните карту памяти, скопируйте блоки будет еще быстрее.

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

1 голос
/ 30 марта 2011

Вот еще один вопрос, который может помочь вам принять решение: Как именно работают fopen (), fclose ()?

Если вы ищете скорость, лучше всегозагрузить весь файл сразу в память и манипулировать им там.Таким образом вы избегаете ненужных обращений к драйверу жесткого диска для предоставления данных.Когда вы начинаете говорить о предоставлении 25 000 000 различных 4-байтовых чанков (при условии 32-битного RGBA) для изображения 5 КБ, вы рассматриваете потенциально много поиска, чтения и ожидания.

Это один изклассическая память против компромисса скорости.Если у ваших клиентов будет достаточно памяти, то лучше всего загрузить все данные в память, а затем выполнить ваши преобразования.

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

1 голос
/ 30 марта 2011

Как правило, я нашел самый быстрый способ работы с файлами - попытаться прочитать все это в памяти одним большим вводом-выводом, а затем обработать его из памяти. Это часто делает код проще тоже.

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

1 голос
/ 30 марта 2011

Это зависит. Вы должны попытаться оценить объем памяти на большинстве компьютеров, на которых будет работать ваше программное обеспечение. Это также зависит от того, насколько критичен ваш код.

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

0 голосов
/ 30 марта 2011

Я собирался написать это как комментарий, но это стало слишком длинным.Но по сути ...

Я согласен с TED и Джонатаном Вудом:

В общем, я нашел самый быстрый способ справиться с файлами - попытаться прочитать весь текст целиком.что-то в память одним большим вводом-выводом, и с этого момента справляется с нехваткой памяти. Это часто делает код более простым.

-TED

Это зависит.Вы должны попытаться оценить объем памяти на большинстве компьютеров, на которых будет работать ваше программное обеспечение.Это также зависит от того, насколько критичен для вашего кода скорость.

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

- Джонатан Вуд

Имейте в виду, что 5000 * 5000 пикселей с 32-битными цветами занимают примерно 100 мегабайт памяти (+ возможно, некоторые накладные расходы, и все, что нужно вашему программному обеспечению)Я бы сказал (по-видимому, значение Стетсона-Харрисона), что большинство современных настольных компьютеров имеют по крайней мере 1 или 2 гигабайта памяти (мой был куплен в 2008 году и имеет 4), так что на самом деле это не так уж много, даже если все это загруженосразу у ноутбуков может быть меньше памяти.

Аспект CUDA также интересен (я почти ничего не знаю о CUDA), данные загружаются в память GPU?Сколько памяти обычно имеют графические процессоры с поддержкой CUDA?Может ли шина PCI-e стать узким местом (вероятно, не ..?)?Узнайте, сколько общей памяти имеют CUDA настольные и портативные графические процессоры с поддержкой CUDA.

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

0 голосов
/ 30 марта 2011

Хранение в памяти определенно будет быстрее. Если вы каждый раз читаете небольшие фрагменты с жесткого диска, вы всегда сталкиваетесь с задержками из-за минимального времени доступа и т. Д.

0 голосов
/ 30 марта 2011

Посмотрите на использование mmap () linux или mapviewoffile () под windows.

...