Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Сегментация большой кучи, работа с большими массивами данных

9.7K
15 марта 2012 года
Vitamant
228 / / 07.02.2011
Доброго времени суток, господа!

Подскажите пожалуйста, что делать в возникшей ситуации:

Нужно считать TIFF-файл объемом 600мб шириной 13000 пикселей, высотой 20000 пикселей. Привести палитру из 24бит к 16 цветам.
Использую BitmapSource и TIFFBitmapDecoder. Считываю N строк в массив байт, равные BitPerPixel / 8 * Width * N методом CopyPixels. Обрабатываю по 3 байта, превращая в цвет, обрабатываю цвет, записываю в новый массив размером width * height индекс цвета в палитре. В конце создаю BitmapSource.Create новый BitmapSource на основе полученных данных, записываю в файл с помощью TIFFBitmapEncoder.

Что в итоге: на каждой итерации цикла чтения, у меня формируется массив размером 13000 * 3 * (100~500) => 3900000 ~ 19500000 байт. Из-за своего размера он попадает в Большую Кучу, предназначенную для долговременного хранения файлов. При попытке вызвать BitmapSource.Create, я получаю OutOfMemoryException (софтина к тому времени отжирает порядка 1Гб оперативки). Сегментированная куча и висящие в ней массивы чудовищных размеров.
Что примечательно: вызов GC.Collect() никак (!!!) не влияет на память - она просто не освобождается. Более того, даже после выхода из метода, то есть когда жизненный цикл переменной подходит к концу, память продолжает оставаться занятой и вторую картинку уже не обработать.

Я понимаю, что читать\писать такие объемы - глупо, однако указанные классы\методы работают именно с полными наборами байт. Метод же CopyPixels работает, похоже, напрямую с файлом, так как чтение по 1ой строке и по 500 строк, во втором случае быстрее раз в... 500.

В виду этого имеется ряд вопросов:
1) Как освобождать большую кучу?
2) Почему она не освобождается сама до завершения программы?
3) Как избежать заполнения и сегментации большой кучи (сейчас подумал, что стоит вынести массив-буфер за пределы цикла, хоть hardcase, в свое время, и говорил, что переменные надо объявлять в той области видимости, где они используются)

И два вопроса менее абстрагированных, которые не заслуживают отдельных тем:
1) Есть ли особенности использования BitmapSource? У него нет метода Dispose, но освобождаться самостоятельно он не спешит.
2) Есть ли другие, менее затратные способы чтения\записи изображений (tiff, gif, pcx, bmp, png), позволяющие работать с небольшими буфферами (меньше 85000 байт) и контролировать работу с памятью? (свободные библиотеки предлагать, самостоятельное описание всех форматов - нет).

Заранее благодарю за любую помощь!
  • Вызывался GC.Collect(2)? от hardcase, 22 марта 2012 года
5
04 апреля 2012 года
hardcase
4.5K / / 09.08.2005
Выделяем память с помощью Marshal.AllocHGlobal. Работатьс ней (читать-писать) можно используя unsafe расширения C#. Альтернативой этому подходу является использование неуправляемых возможностей C++/CLI.
1
15 марта 2012 года
kot_
7.3K / / 20.01.2000
Что касается очистки памяти
Я уже как то писал на форуме по этому поводу - и как раз таки по вопросу обработки картинок - проблема в том, что данная память не помеченная как мусор - поэтому сборщик памяти и не чистит ее. Причина - объекты не достигли своей конца области видимости например, на них существуют ссылки и т.п.
Решением - действительно вынести выделение памяти за пределы цикла, но не видя кода трудно рекомендовать решение.
Учитывая неординарность данной проблемы надо поискать компоненты, которые возможно решают проблему - но вполне возможно что прийдется писать их самому, и возможно используя неуправляемый код. Потому как все же tiff объемом в 600 метров - ну как бы не слишком ординарная задача. ИМХО
5
22 марта 2012 года
hardcase
4.5K / / 09.08.2005
Один из вариантов - выносить большие объемы данных в неуправляемую кучу, так работает Paint.NET
9.7K
28 марта 2012 года
Vitamant
228 / / 07.02.2011
Метод GC.Collect(2) не вызывался, ибо он без параметров прокомментирован в msdn так:
"Принудительно запускает немедленную сборку мусора для всех поколений."
Это неправда?

А можно поподробнее про неуправляемую кучу?
5
04 апреля 2012 года
hardcase
4.5K / / 09.08.2005
Для работы с большими файлами еще можно использовать Memory Mapped Files.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог