Как заставить Java использовать мой многоядерный процессор с GZIPInputStream?

Я использую GZIPInputStream в своей программе, и я знаю, что производительность была бы полезна, если бы я мог заставить Java запускать мою программу параллельно.

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

спасибо!

редактировать

Я запускаю простое обновление Ol ' Java SE 6 17 в Windows XP.

поставил бы GZIPInputStream на отдельный поток явно помогает? нет! Не помещайте GZIPInputStream в отдельный поток! Не многопоточный ввод-вывод!

Изменить 2

Я полагаю, что ввод-вывод является узким местом, поскольку я читаю и пишу на один и тот же диск...

В общем, есть ли способ сделать GZIPInputStream быстрее? Или замена gzipinputstream, который работает параллельно?

редактировать 3 Фрагмент кода я используется:

GZIPInputStream gzip = new GZIPInputStream(new FileInputStream(INPUT_FILENAME)); DataInputStream in = new DataInputStream(new BufferedInputStream(gzip));

9 ответов


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

однако вы можете иметь несколько потоков, каждый из которых распаковывает другой файл.

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

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


PIGZ = параллельная реализация GZip-это полностью функциональная замена gzip, которая использует несколько процессоров и несколько ядер по рукоятке при сжатии данных. http://www.zlib.net/pigz/ это еще не Java - - - любые согласные. Конечно, мир нуждается в Java.

иногда сжатие или декомпрессия является большим потребителем CPU, хотя это помогает I/O не быть узким местом.

см. также Dataseries (C++) от HP Labs. PIGZ только распараллеливает сжатие, в то время как Dataseries разбивает вывод на большие сжатые блоки, которые можно распаковывать параллельно. Также имеет ряд других особенностей.


оберните потоки GZIP в Буферизованные потоки, это должно дать вам значительное повышение производительности.

OutputStream out = new BufferedOutputStream(
    new GZIPOutputStream(
        new FileOutputStream(myFile)
    )
)

и аналогично для входного потока. Использование буферизованных потоков ввода/вывода уменьшает количество считываний диска.


Я не вижу никакого ответа, адресованного другое обработка вашей программы.

если вы просто распаковываете файл, вам лучше просто использовать командную строку gunzip tool; но, вероятно, какая-то обработка происходит с файлами, которые вы вытаскиваете из этого потока.

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

вы можете вручную запустить поток на каждой большой строке или другом блоке данных; но с Java 1.6 или около того вам будет лучше с одним из причудливых новых классов в java.util.concurrent, например,ThreadPoolExecutor.


обновление

мне не ясно из вопроса и других комментариев, действительно ли вы просто извлекаете файлы с помощью Java. Если вы действительно, действительно думаете, что вы должны попытаться конкурировать с gunzip, то вы, вероятно, можете получить некоторая производительность с использованием больших буферов; т. е. работа с буфером, скажем, 10 МБ(двоичный, а не десятичный! - 1048576), заполните это одним глотком и напишите его на диск. Это даст вашей ОС возможность выполнить среднесрочное планирование дискового пространства,и Вам также понадобится меньше системных вызовов.


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


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


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

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


Я думаю, что ошибочно предполагать, что многопоточность IO всегда зло. Вероятно, вам нужно профилировать свой конкретный случай, чтобы быть уверенным, потому что:

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

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

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


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