1

Я пытаюсь реализовать многопоточную рекурсивную логику поиска файлов в Visual C++. Логика такова: Темы 1,2 начинаются с местоположения каталога и соответствуют файлам, присутствующим в каталоге, с критериями поиска. Если они найдут дочерний каталог, они добавят его в рабочую очередь. Когда поток заканчивается файлами в каталоге, он захватывает другой путь каталога из рабочей очереди. Рабочая очередь - это класс STL Stack, защищенный CriticalSections для вызовов push(), pop(), top().Синхронизация доступа к данным между несколькими потоками

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

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

С уважением,

+0

Джерри, Хенк, вы были правы. Я запустил perfmon, как предположил Джерри, и график длины очереди «avg disk queue» подскочил до 100 и остался там в поисках. Единственная причина, связанная с добавлением другого потока, помогла даже слегка из-за сопоставления имени файла. – ivymike

ответ

2

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

Для других типов задач ваша очередь может стать значительным узким местом, но для этой задачи я сомневаюсь. Имейте в виду временные масштабы операций здесь. Простая операция, которая происходит внутри CPU, занимает значительно меньше, чем наносекунда. Чтение из основной памяти занимает порядка десятков наносекунд. Что-то вроде переключения потока или синхронизации занимает порядка нескольких сотен наносекунд или около того. Одно движение головки на диске занимает порядка миллисекунды или около того (1 000 000 наносекунд).

+0

Спасибо Джерри. Есть ли способ проверить, используются ли диски на максимальном уровне на машине Windows. – ivymike

+0

@ivymike: вы можете использовать монитор производительности, чтобы узнать, сколько дискового пространства вы используете, хотя это не даст вам теоретической максимальной пропускной способности. Если память используется, вы также можете проверить глубину очереди на диск, чтобы понять, есть ли команды ввода/вывода, ожидающие выполнения. Вы не заботитесь о полной глубине очереди, только то, что она почти почти не равна нулю (здесь я говорю о очереди ОС, а не о вашей). –

1

В дополнение к ответу Джерри, вашим узким местом является дисковая система. Если у вас есть RAID-массив, вы можете увидеть некоторое умеренное улучшение от использования 2 или 3 потоков.

Если вам нужно найти несколько дисков (обратите внимание: физические диски, а не тома на одном физическом диске), вы можете использовать дополнительные потоки для каждого из них.

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