2013-10-02 4 views
1

У меня есть несколько изображений, которые я фильтрую, и когда я делаю это в последовательной очереди, которую я создаю, память освобождается после завершения каждого блока. Когда я отправляю эту работу в глобальную очередь GCD, память не освобождается и выходит из-под контроля.Использование памяти для глобальной очереди GCD

Я завернул заявления в блок автоматической блокировки, но это, похоже, не имеет значения.

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

Почему память хранится в глобальной очереди и как это можно зафиксировать, чтобы она освобождалась после каждого блока?

+2

Вы должны написать свой код. Из вашего описания невозможно сказать. Семантика автореферации параллельных очередей, как вы видели, непрозрачна и не является непосредственной, поэтому общий совет заключается в том, чтобы обернуть содержимое блоков в @autoreleasepool, которое вы сделали. Я подозреваю, что получаю больше, вам придется дать нам больше возможностей для работы. Например, захватываете ли вы эти изображения при закрытии блока завершения, который вы отправляете в очередь? Если это так, это продлит время жизни изображения до завершения блока завершения. Но да, это трудно посоветовать вам без дополнительной информации. – ipmcc

+0

Это оказалось пулом потоков GCD, несущим множество потоков, каждый из которых содержит огромное отфильтрованное изображение в памяти. Я переключился на параллельную операционную очередь и попробовал разные ограничения параллелизма, пока память не была управляемой. – jarryd

+0

Кроме того, FWIW, если GCD порождает «нагрузки потоков», где нагрузка составляет> 3x количество ядер, это, вероятно, означает, что блоки, которые вы отправляете на него, заканчиваются блокировкой. Более реалистичным подходом было бы сериализовать ввод-вывод в последовательной очереди и параллельно обрабатывать только внутреннюю память. Один из способов получить помощь от GCD в этом отношении - использовать 'dispatch_apply', который ограничит количество параллельных операций. IME 'dispatch_apply' не будет создавать более 2 * # потоков. (Хотя это не учитывает другие одновременные операции, которые могут создавать потоки.) – ipmcc

ответ

2

Вы упомянули в своих комментариях, что GCD, похоже, создает слишком много потоков, вызывая слишком много изображений сразу в памяти. Если GCD порождает «нагрузки потоков», где нагрузка составляет> 3x количество ядер, это, вероятно, означает, что блоки, которые вы отправляете, блокируются (возможно, на вводе/выводе). Более реалистичным подходом было бы сериализовать ввод-вывод в последовательной очереди и параллельно обрабатывать только внутреннюю память. Один из способов получить помощь от GCD в этом отношении - использовать dispatch_apply, который ограничит количество одновременных операций. IME dispatch_apply не будет создавать более чем 2 * число строк. (Хотя это не учитывает другие параллельные операции, которые могут создавать потоки.)

Также, как вы отметили, NSOperationQueue позволяет указать максимальное количество одновременных задач, что является другим подходом.

Смежные вопросы