цифровая электроника
вычислительная техника
встраиваемые системы

 
» » » Сложные математические вычисления на Arduino с помощью библиотеки Intel Math Kernel Library



Сложные математические вычисления на Arduino с помощью библиотеки Intel Math Kernel Library

Автор: Mike(admin) от 20-03-2019, 07:55

Глубокое обучение и другие математические функции для Arduino с помощью Intel MKL


Intel Math Kernel Library – это библиотека математических функций с открытым исходным кодом для приложений глубокого обучения. Библиотека ускоряет процессы глубокого обучения и подобных математических аппаратов. Она содержит векторизованные и многопоточные блоки, которые можно использовать для реализации глубоких нейронных сетей с интерфейсами C и C++.


Сложные математические вычисления на Arduino с помощью библиотеки Intel Math Kernel Library

Несмотря на такую высокую производительность библиотеки, ее можно связать с платформой Arduino, и в этой статье будет показано, как это сделать.


В данном материале мы узнаем, как интегрировать ваш скетч с супероптимизированной библиотекой Intel для сложных математических вычислений. Прежде всего, вам нужен подходящий IoT-шлюз с парой гигабайт свободного места на жестком диске.


Зачем нужно столько места? В мире Arduino библиотека – это набор кода, который помогает вам взаимодействовать с определенным оборудованием или выполнять определенные операции. В Linux библиотека имеет те же свойства, но может использоваться несколькими программами. Это позволяет сэкономить много места, так как содержащаяся в них функция может быть использована другим процессом свободно.


Библиотеки обычно предоставляются через менеджер пакетов или с помощью установщика (мы будем использовать последний в этом примере). Прежде всего, получите доступ к вашей плате через ssh, используя ее IP-адрес и имя пользователя / пароль, которые вы указали при установке. Для этого вы можете использовать Putty (если вы работаете в Windows) или последовательный терминал. Порт должен быть установлен со значением 22 для правильной работы при входе через SSH.


Теперь нам нужно скачать пакет Math Kernel Library (MKL). Откройте браузер и перейдите по адресу https://software.intel.com/en-us/mkl, нажмите «Free Download» и завершите процесс регистрации. Выберите «Intel Performance Libraries for Linux» и щелкните правой кнопкой мыши «Intel Math Kernel Library», выбрав «Копировать адрес ссылки» (или аналогичный пункт, в зависимости от вашего браузера).


Теперь снова откройте оболочку SSH, введите:


wget

И вставьте ссылку, которую вы только что скопировали. Нажмите Enter и загрузка должна начаться. После загрузки распакуйте пакет, набрав:


tar xvf l_mkl_2017*

Зайдите в папку extract (обычно с тем же именем загруженного пакета, без расширения) и наберите:


./install.sh

Следуйте инструкциям на экране, и через пару минут ваша система будет готова.


Откройте Arduino Create с предоставленным примером. Мы собираемся продемонстрировать очень удобную функцию библиотеки MKL, которая помогает распараллеливать выполнение кода, не беспокоясь о потоках. В этом примере матричное умножение выполняется с использованием оптимизированной функции cblas_dgemm, включенной в MKL. Эта функция оптимизирована для различных аппаратных платформ Intel с использованием новейшей функции векторизации, доступной на целевом процессоре (AVX, SSE4 и т. д.).


Что произойдет, если у нас будет многоядерная архитектура? Мы теряем много энергии, потому что функция выполняется только в потоке, даже если проблема, которую она должна решить, «разделяема» на множество мелких задач, поэтому она является идеальным кандидатом для распараллеливания. Используя mkl_set_num_threads, мы можем дать указание библиотеке работать на нескольких потоках (и ядрах) без дополнительных усилий в плане программирования.


В примере выполняются те же вычисления с использованием нескольких номеров потоков, от 1 до количества ядер целевого ЦП (может быть удвоено, если активен HyperThreading) и выполняется сравнение различных прогонов.


Когда все будет готово, откройте монитор на левой панели, нажмите «Upload» и подождите пару секунд, пока не начнется загрузка и создание скетча. Вывод программы будет присутствовать в мониторе.


Сложные математические вычисления на Arduino с помощью библиотеки Intel Math Kernel Library

Если мы посмотрим на результаты, выполнение в двух потоках повысит производительность практически в два раза по сравнению с одиночными потоками (на двухъядерном процессоре, конечно). Влияние на производительность не точно двукратно, так как при запуске любого дополнительного потока возникают некоторые издержки, и эта задержка становится больше, если время выполнения невелико. Если большую часть времени тратить на вычисления чисел, ускорение приближается к теоретическому максимуму. Далее представлен демонстрационный код скетча Arduino.



#include <stdio.h>
#include <stdlib.h>
#include "ArduinoMKL.h"

/* Измените LOOP_COUNT в зависимости от производительности вашего компьютера */
/* чтобы общее время выполнения составило хотя бы 1 секунду */
#define LOOP_COUNT 100

void setup()
{
    double *A, *B, *C;
    int m, n, p, i, j, r, max_threads;
    double alpha, beta;
    double s_initial, s_elapsed;

    printf ("\n This example demonstrates threading impact on computing real matrix product \n"
            " C=alpha*A*B+beta*C using Intel(R) MKL function dgemm, where A, B, and C are \n"
            " matrices and alpha and beta are double precision scalars \n\n");
    
    m = 2000, p = 200, n = 1000;
    printf (" Initializing data for matrix multiplication C=A*B for matrix \n"
            " A(%ix%i) and matrix B(%ix%i)\n\n", m, p, p, n);
    alpha = 1.0; beta = 0.0;
    
    printf (" Allocating memory for matrices aligned on 64-byte boundary for better \n"
            " performance \n\n");
    A = (double *)mkl_malloc( m*p*sizeof( double ), 64 );
    B = (double *)mkl_malloc( p*n*sizeof( double ), 64 );
    C = (double *)mkl_malloc( m*n*sizeof( double ), 64 );
    if (A == NULL || B == NULL || C == NULL) {
        printf( "\n ERROR: Can't allocate memory for matrices. Aborting... \n\n");
        mkl_free(A);
        mkl_free(B);
        mkl_free(C);
        exit(1);
    }

    printf (" Intializing matrix data \n\n");
    for (i = 0; i < (m*p); i++) {
        A[i] = (double)(i+1);
    }

    for (i = 0; i < (p*n); i++) {
        B[i] = (double)(-i-1);
    }

    for (i = 0; i < (m*n); i++) {
        C[i] = 0.0;
    }

    printf (" Finding max number of threads Intel(R) MKL can use for parallel runs \n\n");
    max_threads = mkl_get_max_threads();

    printf (" Running Intel(R) MKL from 1 to %i threads \n\n", max_threads);
    for (i = 1; i <= max_threads; i++) {
        for (j = 0; j < (m*n); j++)
            C[j] = 0.0;
        
        printf (" Requesting Intel(R) MKL to use %i thread(s) \n\n", i);
        mkl_set_num_threads(i);

        printf (" Making the first run of matrix product using Intel(R) MKL dgemm function \n"
                " via CBLAS interface to get stable run time measurements \n\n");
        cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 
                    m, n, p, alpha, A, p, B, n, beta, C, n);
        
        printf (" Measuring performance of matrix product using Intel(R) MKL dgemm function \n"
                " via CBLAS interface on %i thread(s) \n\n", i);
        s_initial = dsecnd();
        for (r = 0; r < LOOP_COUNT; r++) {
            cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 
                        m, n, p, alpha, A, p, B, n, beta, C, n);
        }
        s_elapsed = (dsecnd() - s_initial) / LOOP_COUNT;

        printf (" == Matrix multiplication using Intel(R) MKL dgemm completed ==\n"
                " == at %.5f milliseconds using %d thread(s) ==\n\n", (s_elapsed * 1000), i);
    }
    
    printf (" Deallocating memory \n\n");
    mkl_free(A);
    mkl_free(B);
    mkl_free(C);
    
    if (s_elapsed < 0.9/LOOP_COUNT) {
        s_elapsed=1.0/LOOP_COUNT/s_elapsed;
        i=(int)(s_elapsed*LOOP_COUNT)+1;
        printf(" It is highly recommended to define LOOP_COUNT for this example on your \n"
               " computer as %i to have total execution time about 1 second for reliability \n"
               " of measurements\n\n", i);
    }

    printf (" Example completed. \n\n");
}

void loop() {
  delay(1000);
}



© digitrode.ru


Теги: Arduino, машинное обучение, искусственный интеллект




Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Комментарии:

Оставить комментарий