- PVSM.RU - https://www.pvsm.ru -
В этом посте мы расскажем об использовании библиотеки ускорения аналитики данных Intel Data Analytics Acceleration Library (Intel DAAL) с языком программирования Go для пакетной, интерактивной и распределенной обработки.
На основе Go [1] построены самые современные инфраструктурные проекты, в том числе Kubernetes [2], Docker [3], Consul [4], etcd [5] и многие другие. Go становится предпочитаемым языком для DevOps, веб-серверов и микрослужб. Этот язык прост в изучении, удобен в развертывании, он очень быстрый, для него есть прекрасный набор инструментов разработки.
Обработка и анализ данных используются в бизнесе все чаще, поэтому приходится внедрять ресурсоемкие вычислительные алгоритмы на всех уровнях инфраструктуры компаний, в том числе и на тех уровнях, где используется язык Go. Возникает закономерный вопрос: как интегрировать такие решения как машинное обучение, распределенное преобразование данных и интерактивный анализ данных в системы на основе Go?
Один из способов надежной, быстрой и масштабируемой обработки данных в Go состоит в использовании библиотеки Intel Data Analytics Acceleration Library [6] (Intel DAAL) в программах Go. Эта библиотека предоставляет алгоритмы пакетной, интерактивной и распределенной обработки для целого ряда полезных задач.
Поскольку Go прекрасно взаимодействует с C/C++, можно реализовать эту функциональность в программах Go без особых затруднений. При этом мы существенно выиграем по скорости: эти библиотеки уже оптимизированы для архитектуры Intel. Как показано здесь [7], в определенных операциях, например при анализе основных компонентов, Intel DAAL может работать в семь раз быстрее, чем Spark с MLlib. Это очень здорово! Было бы очень кстати задействовать такую мощь в приложениях Go.
Библиотека Intel DAAL доступна в виде открытого исходного кода [8], для ее установки выполните следующие инструкции [9]. На моем компьютере с Linux это было невероятно просто.
Перед интеграцией Intel DAAL в любую программу Go имеет смысл убедиться, что все правильно работает. Для этого можно воспользоваться различными руководствами по началу работы в документации Intel DAAL [9]. В частности, в этих руководствах предоставляется пример приложения Intel DAAL для алгоритма разложения Холецкого [10]. Ниже мы попробуем создать его на языке Go. Исходный пример алгоритма разложения Холецкого на языке C++ выглядит так.
/****************************************************************************
! Copyright(C) 2014-2017 Intel Corporation. All Rights Reserved.
!
! The source code, information and material ("Material") contained herein is
! owned by Intel Corporation or its suppliers or licensors, and title to such
! Material remains with Intel Corporation or its suppliers or licensors. The
! Material contains proprietary information of Intel or its suppliers and
! licensors. The Material is protected by worldwide copyright laws and treaty
! provisions. No part of the Material may be used, copied, reproduced,
! modified, published, uploaded, posted, transmitted, distributed or disclosed
! in any way without Intel's prior express written permission. No license
! under any patent, copyright or other intellectual property rights in the
! Material is granted to or conferred upon you, either expressly, by
! implication, inducement, estoppel or otherwise. Any license under such
! intellectual property rights must be express and approved by Intel in
! writing.
!
! *Third Party trademarks are the property of their respective owners.
!
! Unless otherwise agreed by Intel in writing, you may not remove or alter
! this notice or any other notice embedded in Materials by Intel or Intel's
! suppliers or licensors in any way.
!
!****************************************************************************
! Content:
! Cholesky decomposition sample program.
!***************************************************************************/
#include "daal.h"
#include <iostream>
using namespace daal;
using namespace daal::algorithms;
using namespace daal::data_management;
using namespace daal::services;
const size_t dimension = 3;
double inputArray[dimension *dimension] =
{
1.0, 2.0, 4.0,
2.0, 13.0, 23.0,
4.0, 23.0, 77.0
};
int main(int argc, char *argv[])
{
/* Create input numeric table from array */
SharedPtr inputData = SharedPtr(new Matrix(dimension, dimension, inputArray));
/* Create the algorithm object for computation of the Cholesky decomposition using the default method */
cholesky::Batch<> algorithm;
/* Set input for the algorithm */
algorithm.input.set(cholesky::data, inputData);
/* Compute Cholesky decomposition */
algorithm.compute();
/* Get pointer to Cholesky factor */
SharedPtr<Matrix > factor =
staticPointerCast<Matrix, NumericTable>(algorithm.getResult()->get(cholesky::choleskyFactor));
/* Print the first element of the Cholesky factor */
std::cout << "The first element of the Cholesky factor: "
<< (*factor)[0][0];
return 0;
}
Попробуйте скомпилировать и запустить этот код, чтобы убедиться в успешной установке Intel DAAL. Кроме того, так вы получите представление о том, что мы будем делать на языке Go. Любые вопросы и проблемы, связанные с установкой Intel DAAL, можно обсудить на форуме Intel DAAL [11] (лично для меня этот форум оказался исключительно полезным ресурсом, когда я начал пробовать работать с Intel DAAL).
Если речь идет об использовании библиотеки Intel DAAL в программах на Go, у нас есть несколько возможных вариантов.
Ниже я демонстрирую оба этих подхода. Весь исходный код доступен здесь [12]. Это лишь один пример. Было бы здорово, если бы со временем удалось добавить и другие примеры программ Go с Intel DAAL в это хранилище. При экспериментах, пожалуйста, отправляйте запросы. Мне было бы очень интересно увидеть, что вы создадите.
Если вы раньше не использовали Go, то перед продолжением работы с этой статьей рекомендую получше ознакомиться с этим языком. Отметим, что Go даже не нужно устанавливать на локальный компьютер, чтобы начать его изучать. Можно воспользоваться ознакомлением с Go в Интернете [13] и сайтом Go Playground [14], а уже потом, когда будете готовы, можно установить Go на локальный компьютер [15].
Go предоставляет инструмент под названием cgo [16], который дает возможность создавать пакеты Go, вызывающие код C. В этом случае мы будем использовать cgo для организации взаимодействия нашей программы Go с библиотекой Intel DAAL.
Кстати, использование cgo с программами Go сопряжено с определенными ограничениями, которые достаточно подробно обсуждаются в Интернете (в частности, см. обсуждение Дейва Чени [17] (Dave Cheney) или эту статью [18] компании Cockroach Labs). Принимая решение об использовании cgo, всегда принимайте во внимания эти ограничения или хотя бы просто помните о них. В данном случае мы готовы примириться с ограничениями cgo, чтобы воспользоваться преимуществами оптимизированной распределенной библиотеки Intel DAAL: эти ограничения с лихвой окупятся повышением производительности в определенных случаях с высокой вычислительной нагрузкой или с большими объемами данных.
Для интеграции алгоритма разложения Холецкого из Intel DAAL в программу Go потребуется создать следующую структуру папок (в директории $GOPATH [19]).
cholesky`
├── cholesky.go`
├── cholesky.hxx`
└── cholesky.cxx`
Файл cholesky.go — это наша программа Go, которая будет использовать алгоритм разложения Холецкого из библиотеки Intel DAAL. Файлы cholesky.cxx и cholesky.hxx — это определения/объявления C++, включающие Intel DAAL и указывающие компилятору cgo, какую функциональность Intel DAAL мы будем использовать. Рассмотрим каждый из них.
Сначала файл *.cxx.
#include "cholesky.hxx"
#include "daal.h"
#include <iostream>
using namespace daal;
using namespace daal::algorithms;
using namespace daal::data_management;
using namespace daal::services;
int choleskyDecompose(int dimension, double inputArray[]) {
/* Create input numeric table from array */
SharedPtr inputData = SharedPtr(new Matrix(dimension, dimension, inputArray));
/* Create the algorithm object for computation of the Cholesky decomposition using the default method */
cholesky::Batch<> algorithm;
/* Set input for the algorithm */
algorithm.input.set(cholesky::data, inputData);
/* Compute Cholesky decomposition */
algorithm.compute();
/* Get pointer to Cholesky factor */
SharedPtr<Matrix > factor =
staticPointerCast<Matrix, NumericTable>(algorithm.getResult()->get(cholesky::choleskyFactor));
/* Return the first element of the Cholesky factor */
return (*factor)[0][0];
}
Теперь файл *.hxx.
#ifndef CHOLESKY_H
#define CHOLESKY_H
// __cplusplus gets defined when a C++ compiler processes the file.
// extern "C" is needed so the C++ compiler exports the symbols w/out name issues.
#ifdef __cplusplus
extern "C" {
#endif
int choleskyDecompose(int dimension, double inputArray[]);
#ifdef __cplusplus
}
#endif
#endif
Эти файлы определяют функцию-оболочку choleskyDecompose на C++, использующую алгоритм разложения Холецкого Intel DAAL для разложения входной матрицы и вывода первого элемента множителя Холецкого (как в примере, приведенном в руководстве по началу работы с Intel DAAL). Обратите внимание, что в этом случае наши входные данные — это массив длины размерности матрицы (т. е. матрица 3 х 3 соответствует входному массиву длиной 9). Нужно включить extern “C” в файл *.hxx. В этом случае компилятор C++ будет «знать», что нужно экспортировать соответствующие имена, определенные в наших файлах C++.
После определения функции-оболочки разложения Холецкого в файлах *.cxx и *.hxx можно вызвать эту функцию напрямую из Go. cholesky.go выглядит так.
package main
// #cgo CXXFLAGS: -I$DAALINCLUDE
// #cgo LDFLAGS: -L$DAALLIB -ldaal_core -ldaal_sequential -lpthread -lm
// #include "cholesky.hxx"
import "C"
import (
"fmt"
"unsafe"
)
func main() {
// Define the input matrix as an array.
inputArray := [9]float64{
1.0, 2.0, 4.0,
2.0, 13.0, 23.0,
4.0, 23.0, 77.0,
}
// Get the first Cholesky decomposition factor.
data := (*C.double)(unsafe.Pointer(&inputArray[0]))
factor := C.choleskyDecompose(3, data)
// Output the first Cholesky dcomposition factor to stdout.
fmt.Printf("The first Cholesky decomp. factor is: %dn", factor)
}
Давайте разберем этот процесс поэтапно, чтобы понять, что же тут происходит. Сначала нужно сообщить программе Go, что нужно использовать cgo при компиляции программы, а также нужно компилировать с определенными флагами.
// #cgo CXXFLAGS: -I$DAALINCLUDE
// #cgo LDFLAGS: -L$DAALLIB -ldaal_core -ldaal_sequential -lpthread -lm
// #include "cholesky.hxx"
import "C"
Чтобы использовать, требуется import “C”: это псевдоупаковка, сообщающая об использовании cgo. Если непосредственно перед командой импорта «C» стоит комментарий, то этот комментарий (он называется преамбулой) будет использован в качестве заголовка при компиляции компонентов C++ этого пакета.
С помощью CXXFLAGS и LDFLAGS можно указать флаги компиляции и компоновки, которые cgo должен использовать при компиляции, а нашу функцию C++ можно добавить, используя // #include «cholesky.hxx”. Для компиляции этого примера я использовал Linux и gcc, что и указано выше с помощью соответствующих флагов. Впрочем, можно следовать этому руководству, чтобы определить, как скомпоновать приложение с Intel DAAL.
После этого можно писать код Go таким же образом, как для любой другой программы, и обращаться к нашей функции-оболочке как C.choleskyDecompose().
// Define the input matrix as an array.
inputArray := [9]float64{
1.0, 2.0, 4.0,
2.0, 13.0, 23.0,
4.0, 23.0, 77.0,
}
// Get the first Cholesky decomposition factor.
data := (*C.double)(unsafe.Pointer(&inputArray[0]))
factor := C.choleskyDecompose(3, data)
// Output the first Cholesky dcomposition factor to stdout.
fmt.Printf("The first Cholesky decomp. factor is: %dn", factor)
Уникальная особенность в этом случае (она обусловлена использованием cgo) состоит в том, что нужно преобразовать указатель на первый элемент нашего среза float64 в небезопасный указатель, который затем можно будет явным образом преобразовать в указатель *C.double (совместимый с C++) на нашу функцию choleskyDecompose. Упаковка в небезопасный указатель позволяет нам обойти ограничения безопасности типов, действующие в программах Go.
Отлично! Итак, у нас есть программа Go, которая вызвала алгоритм разложения Холецкого из библиотеки Intel DAAL. Теперь пора собрать и запустить эту программу. Это можно сделать обычным образом с помощью go build.
$ ls
cholesky.cxx cholesky.go cholesky.hxx
$ go build
$ ls
cholesky cholesky.cxx cholesky.go cholesky.hxx
$ ./cholesky
The first Cholesky decomp. factor is: 1
$
И результат готов! Разумеется, первый множитель разложения Холецкого равен 1. Мы успешно воспользовались библиотекой Intel DAAL непосредственно из Go. Впрочем, наша программа на Go выглядит достаточно странно с небезопасными указателями и фрагментами кода C. Кроме того, это одноразовое решение. Теперь попробуем реализовать эту же функциональность в виде многократно используемого пакета Go, который можно будет импортировать точно так же, как и любой другой пакет Go.
Чтобы создать пакет Go, содержащий функциональность Intel DAAL, мы воспользуемся программой SWIG [20]. В Go, помимо использования cgo, можно вызывать SWIG при сборке, чтобы компилировать пакеты Go, реализующие функциональность C/C++. Для такой сборки потребуется создать следующую структуру папок.
choleskylib
├── cholesky.go
├── cholesky.hxx
├── cholesky.cxx
└── cholesky.swigcxx
При этом файлы оболочек *.cxx и *.hxx могут остаться такими же. Но теперь нужно добавить файл *.swigcxx. Этот файл выглядит так.
%{
#include "cholesky.hxx"
%}
%include "cholesky.hxx"
Теперь программа SWIG создает код-оболочку для функции разложения Холецкого, что позволит использовать этот код в качестве пакета Go.
Кроме того, мы создаем пакет Go, пригодный для многократного использования (а не отдельное приложение), поэтому файл *.go может не включать package main или function main. Он должен просто определять имя нашего пакета. В данном случае назовем его cholesky. Теперь cholesky.go будет выглядеть так.
package cholesky
// #cgo CXXFLAGS: -I$DAALINCLUDE
// #cgo LDFLAGS: -L$DAALLIB -ldaal_core -ldaal_sequential -lpthread -lm
import "C"
(Снова указываем файлы в заголовке.)
Теперь можно собрать пакет и установить его локально.
$ ls
cholesky.cxx cholesky.go cholesky.hxx cholesky.swigcxx
$ go install
$
Эта команда компилирует все необходимые двоичные файлы и библиотеки, к которым обращается программа Go, использующая этот пакет. Go «видит», что в нашей папке есть файл *.swigcxx, и автоматически использует SWIG для сборки пакета.
Великолепно! Теперь у нас есть пакет Go, использующий Intel DAAL. Посмотрим, как сработают импорт и использование пакета.
package main
import (
"fmt"
"github.com/dwhitena/daal-go/choleskylib"
)
func main() {
// Define the input matrix as an array.
inputArray := [9]float64{
1.0, 2.0, 4.0,
2.0, 13.0, 23.0,
4.0, 23.0, 77.0,
}
// Get the first Cholesky decomposition factor.
factor := cholesky.CholeskyDecompose(3, &inputArray[0])
// Output the first Cholesky dcomposition factor to stdout.
fmt.Printf("The first Cholesky decomp. factor is: %dn", factor)
}
Класс! Такой код намного чище по сравнению с прямым использованием Intel DAAL. Можно импортировать пакет алгоритма Холецкого, как и любой другой пакет Go, и вызвать заключенную в оболочку функцию как cholesky.CholeskyDecompose(...). Кроме того, в SWIG были автоматически обработаны и все небезопасные компоненты. Теперь можно просто передать адрес первого элемента нашего исходного среза float64 в cholesky.CholeskyDecompose(...).
Эту программу, как и любую другую программу на языке Go, можно скомпилировать и запустить командой go build:
$ ls
main.go
$ go build
$ ls
example main.go
$ ./example
The first Cholesky decomp. factor is: 1
$
Ура! Все правильно. Теперь можно использовать этот пакет в других программах Go, если нам потребуется алгоритм разложения Холецкого.
С помощью Intel DAAL, cgo и SWIG нам удалось встроить оптимизированный алгоритм разложения Холецкого в программы на языке Go. Разумеется, возможности не ограничиваются только этим алгоритмом. Аналогичным образом можно создавать программы и пакеты на языке Go, использующие любые алгоритмы, реализованные в Intel DAAL. Можно создавать нейросети с пакетной, интерактивной и распределенной обработкой, кластеризацией, ускорением, совместной фильтрацией и другими возможностями непосредственно в приложениях Go.
Весь использованный выше код доступен здесь [12].
Ресурсы по языку программирования Go
Ресурсы по DAAL
Дэниэл (@dwhitena) — доктор наук, опытный исследователь данных, он работает в компании Pachyderm (@pachydermIO). Он занимается разработкой современных распределенных конвейеров данных, включающих предсказательные модели, визуализацию данных, статистический анализ и другие возможности. Он выступал на конференциях в разных странах мира (ODSC, Spark Summit, Datapalooza, DevFest Siberia, GopherCon b lheubt), преподает исследование и анализ данных в компании Ardan Labs (@ardanlabs), поддерживает ядро Go для Jupyter и активно участвует в развитии различных проектов по интеллектуальному исследованию данных с открытым исходным кодом.
Автор: Виктор Гурылев
Источник [27]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/264173
Ссылки в тексте:
[1] Go: https://golang.org/
[2] Kubernetes: https://kubernetes.io/
[3] Docker: https://github.com/docker/docker
[4] Consul: https://www.consul.io/
[5] etcd: https://github.com/coreos/etcd
[6] Intel Data Analytics Acceleration Library: https://software.intel.com/en-us/intel-daal
[7] здесь: https://software.intel.com/en-us/blogs/daal
[8] открытого исходного кода: https://01.org/daal
[9] следующие инструкции: https://software.intel.com/en-us/intel-daal-support/documentation
[10] алгоритма разложения Холецкого: https://en.wikipedia.org/wiki/Cholesky_decomposition
[11] форуме Intel DAAL: https://software.intel.com/en-us/forums/intel-data-analytics-acceleration-library
[12] здесь: https://github.com/dwhitena/daal-go
[13] ознакомлением с Go в Интернете: https://tour.golang.org/welcome/1
[14] Go Playground: https://play.golang.org/
[15] установить Go на локальный компьютер: https://golang.org/doc/install
[16] cgo: https://golang.org/cmd/cgo/
[17] обсуждение Дейва Чени: https://dave.cheney.net/2016/01/18/cgo-is-not-go
[18] эту статью: https://www.cockroachlabs.com/blog/the-cost-and-complexity-of-cgo/
[19] $GOPATH: https://golang.org/doc/code.html#GOPATH
[20] SWIG: http://www.swig.org/
[21] Gophers on Slack: https://invite.slack.golangbridge.org/
[22] GopherData: http://gopherdata.io/
[23] GopherData: https://twitter.com/GopherDataIO
[24] инструментов для Go: https://github.com/gopherdata/resources/tree/master/tooling
[25] документацией: https://software.intel.com/en-us/intel-daal/documentation
[26] учебными материалами: https://software.intel.com/en-us/intel-daal-support/training
[27] Источник: https://habrahabr.ru/post/338002/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.