Случайная полная система не отвечает на запросы Выполнение математических функций - PullRequest
6 голосов
/ 23 февраля 2010

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

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

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

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

Что я сделал:

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

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

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

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

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

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

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

Любой совет будет приветствоваться.

Ответы [ 6 ]

3 голосов
/ 23 февраля 2010

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

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

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

1 голос
/ 13 мая 2010

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

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

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

1 голос
/ 24 февраля 2010

Мне нравятся предложения по кешированию / перебрасыванию дисков, но если это не так, вот несколько советов:

С какими библиотеками, не относящимися к MSVC, если они есть, вы ссылаетесь?

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

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

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

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

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

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

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

1 голос
/ 24 февраля 2010

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

1 голос
/ 23 февраля 2010

Что нужно проверить:

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

EDIT

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

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

0 голосов
/ 23 февраля 2010

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


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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...