Многоразовая версия конвейера DKPro Core

Я настроил DKPro Core как веб-сервис, чтобы получать входные данные и выдавать токенизированные выходные данные. Сам сервис настроен как ресурс Джерси:

@Path("/")
public class MyResource
{

  public MyResource()
  {
    // Nothing here
  }

  @GET
  public String generate(@QueryParam("q") final String input)
  {
    try
    {
      final JCasIterable en = iteratePipeline(
        createReaderDescription(StringReader.class, StringReader.PARAM_DOCUMENT_TEXT, input, StringReader.PARAM_LANGUAGE, "en")
       ,createEngineDescription(StanfordSegmenter.class)
       ,createEngineDescription(StanfordPosTagger.class)
       ,createEngineDescription(StanfordParser.class)
       ,createEngineDescription(StanfordNamedEntityRecognizer.class)
      );

      final StringBuilder sb = new StringBuilder();
      for (final JCas jCas : en)
      {
        for (final Token token : select(jCas, Token.class))
        {
          sb.append('[');
          sb.append(token.getCoveredText());
          sb.append(' ');
          sb.append(token.getPos().getPosValue());
          sb.append(']');
        }
      }
      return sb.toString();
    }
    catch (final Exception e)
    {
      throw new RuntimeException("Problem", e);
    }
  }
}

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

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

1 ответ

Решение

Создайте один CAS:

JCas jcas = JCasFactory.createJCas();

Заполните CAS

jcas.setDocumentText("This is a test");
jcas.setDocumentLanguage("en");

Создайте конвейер один раз (и оставьте двигатель включенным для дальнейших запросов), используя

AnalysisEngine engine = createEngine(
   createEngineDescription(...),
   createEngineDescription(...),
   ...);

Если вы постоянно создаете движок, он должен загружать модели и т. Д. Снова и снова.

Применить трубопровод к CAS

SimplePipeline.runPipeline(jcas, engine);

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

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

Опять же, вы должны рассмотреть возможность создания пула предварительно созданных конвейеров. Хотя вам понадобится совсем немного памяти, потому что каждый экземпляр будет загружать свои собственные модели. Существует некоторая экспериментальная функциональность для совместного использования моделей между экземплярами одного и того же компонента, но она не слишком проверена. Имейте в виду, что сторонние инструменты также могут реализовывать свои модели без поточной защиты. Для совместного использования моделей в DKPro Core см. Это обсуждение в списке рассылки.

Раскрытие информации: я являюсь одним из разработчиков DKPro Core.

Другие вопросы по тегам