У меня есть что-то вроде проверки орфографии, написанной на Delphi. Он анализирует текст предложение за предложением. Он окрашивает неправильные элементы в соответствии с некоторыми правилами после разбора каждого предложения. Пользователь может прервать этот процесс, что важно. Как я могу распараллелить этот процесс в целом, используя некоторые сторонние библиотеки Delphi? В текущем состоянии у меня есть окраска предложения на лету после проверки. Таким образом пользователь видит прогресс.
Как я могу распараллелить проверку орфографии с помощью Delphi?
- Обратите внимание, что вопрос о том, как распараллелить это, не зависит (или должен быть) от какой-либо сторонней библиотеки. Сначала вам нужна стратегия, затем вы можете решить, какие инструменты использовать для ее реализации. 15.06.2012
- Хорошо, тогда мне нужен пример такой стратегии. Конкретные средства (например, прямое создание потоков или их использование через стороннюю библиотеку) менее важны. 15.06.2012
- Зачем вам нужно распараллеливать отображение проверки орфографии, которая охватывает один экран? 15.06.2012
- Если вы все еще хотите сделать это многопоточным (после прочтения действительного вопроса Дэвида) и вы новичок в многопоточности, не сворачивайте свои собственные. Используйте библиотеку OmnithreadLibrary (OTL). 15.06.2012
- Параллелизм не решает проблему медлительности. Вы должны оптимизировать алгоритм, потому что он непригоден, если пользователю приходится слишком долго ждать. 15.06.2012
- Одна важная вещь, пожалуйста, уточните, должна ли проверка орфографии вызываться при изменении текста или по команде пользователя. 15.06.2012
- @LU RD: он будет перепроверять только предложение, в котором произошло изменение. Если у нас есть 100 предложений и ПК с 2 ядрами, то это будет нормально, если прибл. 50 предложений будут проверяться одним ядром, а остальные — другим. 15.06.2012
- @hubalu Я тоже пытаюсь найти и устранить узкие места. Но будет круто, если у меня будет ускорение 1,7х для ПК с 2 ядрами, например. 15.06.2012
- @David Heffernan: проверка орфографии является подзадачей, также проверяется грамматика. Это своего рода анализатор предложений. 15.06.2012
Ответы:
Алгоритм будет таким:
- Создайте несколько рабочих.
- Создайте проверку правописания в каждом воркере.
- Возьмите текст и разделите его на рабочие единицы (слова или предложения). Каждая единица работы должна сопровождаться указанием местоположения в исходном тексте.
- Отправка рабочих единиц рабочим. Хорошим подходом является отправка данных в общую очередь, из которой рабочие берут единицы работы. Очередь должна либо поддерживать несколько считывателей, либо вы должны использовать блокировку для доступа к ней.
- Each worker takes a work unit, runs a spell-check and returns the result (together with the location in the original text) to the owner.
- The simplest way to return a result is to send a message to the main thread.
- В качестве альтернативы вы можете записать результаты в очередь результатов (которая должна либо использовать блокировку, либо поддерживать несколько модулей записи), а затем приложение может опрашивать эти результаты (либо с помощью таймера, либо с помощью обработчика OnIdle).
Другая проблема заключается в том, как несколько программ проверки орфографии будут получать доступ к словарю. Вы можете загрузить копию словаря в каждый воркер или защитить доступ к словарю блокировкой (но это замедлит работу). Если вам повезет, словарь является потокобезопасным для чтения, и вы можете выполнять одновременные запросы без блокировки.
Подходящей абстракцией OmniThreadLibrary для решения проблемы может быть либо ParallelTask или BackgroundWorker.
Для распараллеливания достаточно создать новый класс-потомок от TThread, создать из него объект, отдать часть задания новому потоку, запустить Execute и собрать результаты в основном потоке.
Так:
TMySpellChecker = class(TThread)
protected
FText: String;
FResult: String;
public
procedure Execute; override;
property Text: String read FText write FText;
property Result: String read FResult write FResult;
end;
TMySpellChecker.Execute;
begin
// Analyze the text, and compute the result
end;
В основной теме:
NewThread := TMySpellChecker.Create(True); // Create suspended
NewThread.Text := TextSegment;
NewThread.Execute;
Затем объект потока будет выполнять анализ в фоновом режиме, в то время как основной поток продолжает работать.
Для обработки результатов необходимо назначить обработчик событию OnTerminate объекта потока:
NewThread.OnTerminate := HandleMySpellCheckerTerminate;
Это необходимо сделать до того, как вы запустите Execute для объекта потока.
Чтобы допустить прерывание, одна из возможностей состоит в том, чтобы разбить основной текст на сегменты, поместить сегменты в список в основном потоке, а затем проанализировать сегменты один за другим, используя объект потока. Затем вы можете разрешить перерывы между каждым запуском.