Случайная безразличность полной системы, выполняющая математические функции

У меня есть программа, которая загружает файл (где угодно от 10 МБ до 5 ГБ), блок за один раз (ReadFile), и для каждого блока работает, ряд математических операций (в основном вычисляет хеш).

После вычисления хеша это хранит информацию о блоке в карте STL (в основном <chunkID, hash>) и затем пишет сам блок в другой файл (WriteFile).

Это - все, что это делает. Эта программа заставит определенные ПК дросселировать и переставать работать. Мышь начинает заикаться, диспетчер задач берет>, 2 минуты для показа ctrl+alt+del безразличен, запускающие программы являются медленными.... работы.

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

Что я сделал:

  • Испытанные различные (менее интенсивные) алгоритмы хеширования.
  • Переключенный все выделения на nedmalloc вместо нового оператора по умолчанию
  • Переключенный с stl:: отобразитесь на unordered_set, нашел, что производительность все еще была плачевна, таким образом, я переключился снова на dense_hash_map Google.
  • Преобразованный все объекты сохранить указатели на объекты вместо самих объектов.
  • Кэширование всех Операций чтения и Операций записи. Вместо того, чтобы читать 16k блок файла и выполнить математику на нем, я считал 4 МБ в буфер и считал блоки 16k оттуда вместо этого. То же для всех операций записи - они объединяются в блоки 4 МБ прежде чем быть записанным в диск.
  • Выполните обширное профилирование с Visual Studio 2010, Аналитик Кода AMD и perfmon.
  • Установите приоритет потока на THREAD_MODE_BACKGROUND_BEGIN
  • Установите приоритет потока на THREAD_PRIORITY_IDLE
  • Добавленный Сон (100) вызов после каждого цикла.

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

Perfmon и Process Explorer показывают минимальное использование ЦП (со сном), никакие постоянные чтения/записи от диска, немного трудных отсутствий страницы (и только ~30k отсутствия страницы во время жизни приложения на входном файле на 5 ГБ), мало виртуальной памяти (никогда, чем 150 МБ), никакие пропущенные дескрипторы, никакие утечки памяти.

Машины я протестировал его на выполненном Windows XP - включенные версии Windows 7, x86 и x64. Ни один не имеет меньше чем 2 ГБ RAM, хотя проблема всегда усиливается при более низких условиях памяти.

Я в замешательстве относительно того, что сделать затем. Я не знаю то, что вызывает его - я порван между ЦП или Памятью как преступник. ЦП, потому что безо сна и под различными приоритетами потока производительности системы изменяется заметно. Память, потому что существует огромная разница в том, как часто проблема происходит при использовании unordered_set по сравнению с dense_hash_map Google.

Что является действительно странным? Очевидно, дизайн ядра NT, как предполагается, предотвращает этот вид поведения от когда-либо появления (приложение непривилегированного режима, управляющее системой к этому виду экстремальной низкой производительности!?)....., но когда я компилирую код и выполняю его на OS X или Linux (это - довольно стандартный C++ повсюду) это работает превосходно даже на плохих машинах с небольшой RAM и более слабыми центральными процессорами.

Что я, как предполагается, делаю затем? Как я знаю то чем, черт возьми, случается так, что Windows делает негласно, это уничтожает производительность системы, когда все индикаторы - то, что само приложение ничего не делает экстремальное значение?

Любой совет приветствовался бы.

6
задан Mahmoud Al-Qudsi 23 February 2010 в 16:09
поделиться

6 ответов

Оказывается, это ошибка компилятора Visual Studio. Использование другого компилятора полностью решает проблему.

В моем случае я установил и использовал компилятор Intel C ++, и даже при отключенной оптимизации я не заметил полного зависания системы, которое у меня было с компиляторами Visual Studio 2005 - 2010 в этой библиотеке.

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

1
ответ дан 17 December 2019 в 00:08
поделиться

Некоторые вещи для проверки:

  • Антивирусное программное обеспечение. Они часто сканируют файлы при их открытии для проверки на вирусы. Имеется ли у вас задержка до того, как приложение прочитает какие-либо данные?
  • Общая производительность системы. Показывает ли эта проблема и копирование файла с помощью проводника?
  • Ваш код. Разбейте его на различные этапы. Напишите программу, которая просто читает файл, затем программу, которая читает и записывает файлы, затем программу, которая просто хеширует случайные блоки оперативной памяти (т.е. удаляет часть ввода-вывода диска), и посмотрите, является ли какой-либо конкретный шаг проблематичным. Если вы можете получить профилировщик, используйте его, чтобы увидеть, есть ли в вашем коде медленные места.

РЕДАКТИРОВАТЬ

Еще идеи. Возможно, ваша программа слишком сильно удерживает блокировку GDI. Это объяснило бы, что все остальное работает медленно без высокой загрузки ЦП. Только одно приложение одновременно может иметь блокировку GDI. Это приложение с графическим интерфейсом или просто консольное приложение?

Вы также упомянули RtlEnterCriticalSection.Это дорогостоящая операция, и она может довольно легко повесить систему, т. Е. Несовпадение входов и выходов. Вы вообще многопоточны? Причина замедления в гонке между потоками?

1
ответ дан 17 December 2019 в 00:08
поделиться

XPerf - ваш проводник. Посмотрите видео PDC об этом, а затем найдите некорректно работающее приложение. Он точно скажет вам, что происходит во всей системе, он чрезвычайно мощный.

1
ответ дан 17 December 2019 в 00:08
поделиться

Мне нравятся предложения по кэшированию / перегрузке диска, но если это не так, то вот несколько предложений scattershot:

На какие не-MSVC библиотеки, если таковые имеются, вы ссылаетесь?

Можно ли изменить вашу программу (# ifdef'd) работать без графического интерфейса? Возникла ли проблема?

Вы добавили :: Sleep (100) после каждого цикла в каждом потоке, верно? О скольких потоках вы говорите? Горстка или сотни? Сколько примерно времени занимает каждая петля? Что произойдет, если вы сделаете это :: Sleep (10000)?

Возможно, ваша программа делает что-то еще, что блокирует ограниченные ресурсы (ProcExp может показать вам, какие дескрипторы собираются ... конечно, у вас могут быть проблемы с ProcExp, а не ответ: - [)

Вы уверены, что CriticalSections предназначены только для пользователя? Я вспоминаю, что это было так, когда я работал над Windows (или мне так казалось), но Microsoft могла это изменить. Я не вижу никаких гарантий в статье MSDN Critical Section Objects ( http://msdn.microsoft.com/en-us/library/ms682530%28VS.85%29.aspx ) ... и это заставляет меня задуматься: Антиконвойные блокировки в Windows Server 2003 SP1 и Windows Vista

Хммм ... по-видимому, сейчас мы все многопроцессорные, так что вы устанавливаете счетчик оборотов на CS?

Как насчет запуска отладочной версии одной из этих ОС и мониторинга вывода отладки ядра (с помощью DbgView) ... возможно, используя отладчик ядра из Platform SDK ... если MS все еще вызывает его это?

Интересно, может ли VMMap (еще одна служебная программа SysInternal / MS) помочь с гипотезой о кэшировании диска.

1
ответ дан 17 December 2019 в 00:08
поделиться

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


Добавлено: вы говорите, что он хорошо работает в OSX и Linux и плохо работает в Windows. Я предполагаю, что отношение времени выполнения - довольно большое число, например, 10 или 100, если у вас даже хватило терпения дождаться этого. Я сказал это в комментарии, но это ключевой момент. Программа чего-то ждет, а вам нужно узнать что. Это может быть что угодно из упомянутого людьми, но это не случайно .

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

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

Извините за такую ​​элементарность, , но многие люди ( и создатели профилировщиков ) не понимают . Они думают, что нужно измерить.

0
ответ дан 17 December 2019 в 00:08
поделиться

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

Когда вы запускаете приложение в файле, скажем, от 1/4 до 1/2 размера доступной физической памяти, работает ли оно лучше?

Я подозреваю, что может происходить то, что Windows "помогает" кэшировать ваш диск читает в память и не передает эту кеш-память вашему приложению для использования, вынуждая ее перейти на свопинг. Таким образом, даже несмотря на то, что использование свопа минимально (150 МБ), оно постоянно входит и выключается по мере вычисления хэша. Это ставит систему на колени.

3
ответ дан 17 December 2019 в 00:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: