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

 
» » » Сложные математические вычисления на 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, машинное обучение, искусственный интеллект



   Благодарим Вас за интерес к информационному проекту digitrode.ru.
   Если Вы хотите, чтобы интересные и полезные материалы выходили чаще, и было меньше рекламы,
   Вы можее поддержать наш проект, пожертвовав любую сумму на его развитие.


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

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

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