Статьи

Акка и Куда

Давайте продолжим наше обсуждение нативных компонентов, которые реагируют на сообщения от Akka. Мы подключим реальную обработку изображений к нашему C ++ коду. Чтобы сделать это еще более интересным, я покажу вам, как использовать сборку OpenCV с поддержкой CUDA.

Основные компоненты

У нас есть три основных компонента: JVM, размещенный ActorSystemс несколькими участниками, которые отправляют запросы на обработку изображений через RabbitMQ в собственное приложение, которое привязывается к соответствующим очередям.

Другой важной деталью является то, что приложение Akka отправляет один запрос , но получает поток ответов . В коде, который я показываю на https://github.com/janm399/akka-patterns , ответы все одинаковые, но можно легко представить, что нативный компонент начинает обрабатывать видеопоток и отправляет только интересные последовательности клиенту , (Это может быть обнаружение движения, необычное поведение человека, мониторинг производственных процессов,…).

Почему родной, спросите вы? Ну, чтобы показать, что такая интеграция действительно возможна, и позволить мне написать код, который максимально использует ваш графический процессор. (Знаете ли вы, что вы можете получить 1 машину tera-FLOPS от Amazon за 2,40 доллара в час ?!)

Механизм

RabbitMQ — наш брокер сообщений. Он получает запросы из кода Akka, направляет их в соответствующую очередь, где серверный компонент забирает их.

  1. ConnectionOwner.createChildActor(connection, Props(new RpcStreamingClient()))создает
    актера, который будет говорить по RabbitMQ. Каждый участник создает личную исключительную очередь, которую он использует
    для ответов.
  2. channel->BindQueue("image", "amq.direct", "image.key");привязывает слушателя
    к очереди. Затем он получает тег доставки и использует его для синхронного ожидания
    прибытия сообщения путем вызоваEnvelope::ptr_t env = channel->BasicConsumeMessage(tag);
  3. client ! Request(Publish("amq.direct", "image.key", ...))
    Клиент посылает некоторую полезную нагрузку на amq.directобмен и указывает
    на image.keyклавишу маршрутизации. RabbitMQ проверяет ключ маршрутизации и помещает
    запрос в очередь, указанную ключом маршрутизации обмена.
  4. Завершает channel->BasicConsumeMessage(tag)и возвращает сообщение,
    clientопубликованное.
  5. M * a * g * i * c & p * o * n * i * e * s
  6. Сервер создает ответ и отправляет его клиенту, вызывая channel->BasicPublish("", replyTo, response, true);

Нативный код

Начнем с рассмотрения нативного компонента. Это довольно простой бизнес cmake.org , для которого требуются клиенты RabbitMQ C и C ++, Boost и OpenCV. Первые три — это простые установки, даже на OS X. Для сборки OpenCV нужно немного поиграться, чтобы она работала с CUDA на OS X. (Если вы работаете в Linux, пропустите следующий раздел; если вы в Windows Мне жаль твою душу.)

CUDA OpenCV на OS X

Загрузите и установите последние пакеты CUDA. Затем загрузите исходные коды OpenCV. Чтобы построить его, следуйте обычному рецепту cmake. Создайте buildкаталог и перейдите в него. Перед сборкой, редактировать cmake/OpenCVDetectCUDA.cmakeзакомментировав return()ин

if (NOT MSVC AND NOT CMAKE_COMPILER_IS_GNUCXX OR MINGW)
   message(STATUS "CUDA compilation was disabled (due to...).")
   # return() <-- commented
 endif()

Затем вы должны настроить сгенерированный CMakeCache.txt(дрожит!), Изменив CMakeCache.txt:CUDA_HOST_COMPILER:FILEPATHсвойство с /usr/bin/ccна/usr/bin/gcc

CMakeCache.txt:CUDA_HOST_COMPILER:FILEPATH=/usr/bin/gcc

Далее, завершите весь извиняющийся бизнес обычным cmake build и установите заклинания

Строительный демон

Чтобы построить daemonпроект CUDA, перейдите к его источнику и запустите

daemon/src$ mkdir build
daemon/src$ cd build
daemon/src/build$ cmake -G Xcode ..    # to genate XCode project
daemon/src/build$ cmake ..             # to generate makefiles
daemon/src/build$ cmake --build .

Перед его выполнением убедитесь, что у вас imageнастроена очередь и что от amq.directбиржи есть маршрутизация с использованием image.keyключа маршрутизации.

Теперь вы готовы запустить его.

Код Акка / Скала

Код Akka & Scala использует клиент AMQP с https://github.com/janm399/amqp-client . Постройте это сначала; тогда вы готовы использовать сборку и использование кода Akka Patterns.

Примечательным фрагментом кода является тот ClientDemo, который устанавливает соединение с брокером RabbitMQ, создает 16 клиентов и затем отправляет Requestсообщение каждому из них. Это запускает компонент C ++, который затем начинает передавать резонансы каждому клиенту, пока клиент не решит, что с него достаточно (что занимает 100000мс), и остановится сам. Это приводит к тому, что сервер C ++ получает исключение при отправке, что указывает на то, что он должен вернуться к ожиданию другого сообщения от другого клиента.

Хвастаясь

Making most of the GPU gives you amazing number-crunching speed. I ran this codebase on the latest & coolest MacBook Pro with GeForce GT 520M and the CUDA build procesed approximately four times as many messages, while the CPU load remained fairly low. Your results, of course, may vary.

CPU processing:

GPU processing:

Summary

This whole structure shows just how easy it is to build a complex native system that squeezes out as much out of your hardware as possible. The RabbitMQ message broker allows us to easily scale the message rates (this is for another post!), it also ensures safe-ish message delivery and re-delivery in case of failures.

P.S. If you have a lot of images / data that you need to crunch, get in touch. I don’t know why, but I smell a cool project!

P.P.S. A very warm “hi” to my colleagues from 12 years ago! (And yes, Eastern European programmers drink. A lot. And often.)