2014-12-23 3 views
2

Я пишу программу, которая включает в себя анализ файлов CSV минимум 0,5 ГБ (и максимум более 20 ГБ), я прочитал из CSV следующим образом: fstream, while (getline(fin,line)) {}, и в среднем по 17 миллисекунгов работает с каждой записью, разделенной запятой. Простые вещи.Скорость ввода-вывода - ускорение?

Но, есть много записей. Таким образом, очевидно, что программа связана с I/O, но Мне было интересно, могу ли я улучшить производительность ввода-вывода. Я не могу прибегать к OpenMP, поскольку я бы имел дело с ограничениями процессора, и буферизация файла, это большое не будет работать. Так что мне может понадобиться какой-то трубопровод ...

У меня ОЧЕНЬ мало опыта в многопоточности на C++ и никогда не использовались фреймворки потока данных. Может ли кто-нибудь указать мне в правильном направлении?


Update (12/23/14):

Спасибо за все ваши комментарии. Вы правы, 17 мс было немного ... После выполнения профилирования (о, боли) я изолировал узкое место как итерацию по подстроке в каждой записи (75 символов). Я экспериментировал с #pragmas, но это просто недостаточно для распараллеливания. накладные расходы на вызов функции были основной проблемой - теперь 5.41 мкс на запись, сдвинув большой блок. Это уродливо, но быстрее.

Спасибо @ ChrisWard1000 за ваши предложения. К сожалению, я не очень хорошо контролирую аппаратное обеспечение, которое я использую на данный момент, но будет профилировать с большими наборами данных (> 20 ГБ CSV) и посмотреть, как я мог бы ввести разбор массива mmap/multithreaded и т. Д.

+3

Настройте среду профилирования, чтобы узнать, где ваши узкие места. Просто догадываясь, вы, вероятно, могли бы ускорить свою обработку, используя второй поток, потому что 17 мс - это время на полпути современного компьютера, и за это время он привязан к процессору. –

+0

Вам определенно нужно настроить среду профилирования. Вам нужно знать, сколько времени потребуется для последовательного чтения всего файла без промежуточной обработки. Время получить данные через память, чтобы вы могли сделать что-то еще с этим, будет ограничено с такой скоростью (т. Е. Вы просто не сможете обрезать данные быстрее, чем ваши шпиндели могут доставить его). Если ваше текущее общее время значительно * больше *, чем минимальное время чтения, потенциально может быть область для улучшения путем разгрузки чтения в async-io и отправки фактической обработки в рабочий поток или пул. – WhozCraig

+0

ОС читает заранее. Часто вызов чтения является только memcpy. Но, похоже, вам нужно доказать, что вы сначала связаны с IO. При 160 записях в секунду это не похоже на это. – usr

ответ

8

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

  1. Обновление аппаратного обеспечения. Диски SSD, RAID и жесткие диски PCI Express предназначены для такого рода деятельности.

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

  3. Рассмотрите возможность использования mmap для отображения указателя между жестким диском и памятью.

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

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

+0

Спасибо за ваши многочисленные предложения! См. Обновление для op, я резко сократил 17 мс, и теперь мне просто нужно поэкспериментировать с большими наборами данных, чтобы проверить истинную производительность ввода-вывода. – PidgeyBAWK

0

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

0

Проблема с большинством профайлеров, как вы выяснили, либо они 1) игнорировать вашу I/O, или они 2) только дать вам времени функционировать на уровне, не выстраиваться уровня.

Очень простой способ дает вам оба, shown here.

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

Если вы обрабатываете только 160 записей в секунду, вы не привязываетесь к вводу/выводу, вы связаны с ЦП, и почти каждая пауза будет указывать на ваш синтаксический анализ или что-то еще. Например, вы можете указать new ing (и позже удалить) много объектов. Если да, повторите их использование.

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

Промыть и повторить. Когда вы будете связаны с I/O, вы можете остановиться.

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