---
abstract: 'One of the barriers to the adoption of parallel computing is the inherent complexity of its programming. The Open Multi-Processing (OpenMP) Application Programming Interface (API) facilitates such implementations, providing high abstraction level directives. On another front, new architectures aimed at low energy consumption have been developed, such as the Greenwaves Technologies GAP8, a Multi-Processor System-on-Chip (MPSoC) based on the Parallel Ultra Low Power (PULP) Platform. The GAP8 has an 8-core cluster and a Fabric Controller(FC) master core. Parallel programming with GAP8 is very promising on the efficiency side, but its recent development and lack of a robust OS to handle threads and core scheduling complicate a simple implementation of the OpenMP APIs. This project implements a source to source translator that interprets a limited set of OpenMP directives, and is capable of generating parallel microcontroller code manipulating the cores directly. The preliminary results obtained in this work shows a reduction of the code size, if compared with the base implementation, proving the efficiency of the project to ease the programming of the GAP8. Further work is need in order to implement more OpenMP directives.'
author:
- Reinaldo Agostinho de Souza Filho
- 'Diego V. Cirilo do Nascimento'
- 'Samuel Xavier-de-Souza'
bibliography:
- 'bibliography.bib'
subtitle: '*Position Paper*'
title: An OpenMP translator for the GAP8 MPSoC
---

Introduction {#sec:introduction}
============

Over 17 billion Internet of Things (IoT) devices were connected in 2018 @iotgrow. Such devices have tight energy budgets, due to dimensions, battery size and heat dissipation constraints. Efficiency is the key to overcome these limitations while providing the required performance, demanding efforts from both the hardware and the software fronts.

New Instruction Set Architectures (ISAs), such as the RISC-V were created with energy efficiency as a goal @risc-v, as well as new devices as the Greenwaves Technologies GAP8, a Multi-Processor System on Chip (MPSoC) based on the Parallel Ultra Low Power (PULP) platform @gap_aval [@gap8].

The PULP Platform started as a joint effort between the Integrated Systems Laboratory (IIS) of Eidgenössische Technische Hochschule (ETH) Zürich and Energy-efficient Embedded Systems (EEES) group of the University of Bologna in 2013 to explore new and efficient architectures for ultra-low-power processing. The aim is to develop an open source, scalable hardware and software research and development platform with the goal to break the energy efficiency barrier within a power cost of a few milliwatts, as well as satisfy the computational demands of IoT applications requiring flexible processing of data @pulp.

Although it stands out as an innovative technology, one of the limiting factors to the popularization of GAP8 is the complexity of its parallel programming. At the time of this writing, there is no support to more complex operating systems, capable of managing parallel operations. Presently GAP8 supports three Real Time Operating System (RTOS): Mbedos, PULPOS and FreeRTOS. None is able to assign threads to specific hardware cores using functions such as pthreads. The Software Development Kit (SDK) of GAP8 supports the C and C++ programming languages.

OpenMP is an open source API developed by the OpenMP Foundation that aims to offer paralelization directives in a higher abstraction level than the usual native APIs, reducing the complexity of implementation of parallel applications.

The goal of this project is to develop an OpenMP source to source translator for the GAP8, simplifying the development of parallel applications for the architecture.

Currently, this translator implements the following OpenMP directives, clauses and functions:

<span>2</span>

1.  `parallel`

2.  `for`

3.  `parallel for`

4.  `critical`

5.  `single`

6.  `num_threads`

7.  `reduction`

8.  `private`

9.  `shared`

10. `omp_get_thread_num()`

11. `omp_get_num_threads()`

Parallel Programming in the GAP8 {#sec:cap2}
================================

GAP8 is an open-source IoT processor that implements an extended version of the RISC-V instruction set. It is composed of one Fabric Controller (FC) core, and eight cores in a cluster. Each core on the cluster has its own data cache. GAP8 is uniquely optimized to perform high-performance imaging and audio processing algorithms including convolutional neural network inference with extreme energy efficiency @gap_manual. The Figure \[fig:gap8-arch\] shows the architecture of the GAP8.

![GAP8 architecture @gap_manual.<span data-label="fig:gap8-arch"></span>](fig/gap_arch.png){width="90.00000%"}

A Software Development Kit (SDK) is provided by the manufacturer, and allow the programming of the system in C or C++. Besides the usual peripheral and setup functions, functions for controlling the parallel operations are provided @gap_SDK.

Cluster usage
-------------

The RTOS runs on the FC core, and parallel operations must be offloaded to the cluster. The cluster is able to run on an independent voltage and frequency domain, and is turned off by default, aiming to reduce the power consumption.

The first step is to issue the `CLUSTER_Start(0, number_of_cores)` function power-up the cluster. `CLUSTER_SendTask(0, Master_entry, (void*) data, 0)` will send the task to the cluster.

This task is a previously defined on the master function with arguments (data) that must be a void pointer and return to the original value later with a cast for the desired type all that is sent to the cluster with a function to fork to the cores on cluster.

Within the `Master_entry` the function `CLUSTER_CoresFork(function, data)` is called, and that basically replicates the function that must also be previously created for the cluster passing data (or as you would like to call its argument) as argument.

The data that is passed by reference, using structures or vectors to access all the necessary arguments.

Another problem would be not being able to reset the `Master_Entry` which limits multiple parallel regions to do different functionality, having to create n master functions for n regions besides the n functions to be fired.

Memory allocation
-----------------

Private data can be directly passed to the cluster using `L1_Malloc(size)` so the cluster elements can access directly from their own memory then need to issue a `L1_Free(size)` to clean the L1 memory address data from the cluster allowing to use it again without false fully memory of the program. This post-allocation data should be sent as previously said by the master to the functions that should handle them.

If you need to have a variable that needs to be accessed by the FC and the cluster, it must be global.

Shutting down the Cluster
-------------------------

To terminate the cluster work you must use the `CLUSTER_Stop()` function, and have the option to use `CLUSTER_Wait()` before to ensure that all cores finish before stopping the group. It is worth remembering that `L1_Free` should be used before stopping the cluster otherwise there will not be another chance.

The basics of the translator
============================

A C code is passed as argument to the code `rei_omp.py`. The code is sent to an output folder that must be created before execution with the name `output`. The code created has the same name as the one passed as parameter added with `_gap` before the `.c`. A Diagram is show on Figure \[fig:parser\].

Tests and Results {#sec:cap5}
=================

For verifying the operation of the developed code, tests were selected from the source codes of the book of Peter Pacheco Parallel computing @pacheco. All code requests input and output, for a embedded device this is not reality although there is a version of `printf` made for GAP\_SDK it is really necessary to adapt the code to work on a embedded device, respecting the idea of algorithms and all their directives. The ratio of the original program to the generated program is considerable, the programs had very similar or equal results in the tests, we use the following programs.

1.  `omp_hello.c` – A "Hello World" in parallel;

2.  `omp_pi.c` – The calculation of $\pi$;

3.  `omp_trap2a.c` – Trapezoidal rule integration.

In addition to the `hello_for.c`and `hello_cru.c` codes of our authorship based on own gap\_sdk programs

The number of rows of the original OpenMP codes compared to the generated codes can be seen in the following table:

       Source       Original number of lines   Converted code lines   Reduction percentage
  ---------------- -------------------------- ---------------------- ----------------------
     `omp_pi.c`                40                      135                    70%
   `omp_trap2a.c`              98                      265                    63%
   `omp_hello.c`               22                       79                    72%
   `hello_for.c`               24                      121                    80%
   `hello_cru.c`               49                      266                    81%

  : Code lines comparison

\[tab:line\_code\]

omp\_pi.c estimates de value of pi, omp\_trap2a.c calculates an integral with the trapezoidal rule, omp\_hello is a simple parallel hello world, hello\_for is a program used to debug exclusively the for loop, hello\_cru.c combines all directives and clauses the last two were made by purpose of tests and the others Parallel Programming adapted codes to run in GAP8(excluding inputs and adding libraries) to validate the project.

It is noticeable the decrease of writing work of the programmer, since the functionality keeps considering the restrictions of a System on chip (SoC) we have a gain of time that can be valuable for a programmer.

Conclusion {#sec:conclusion}
==========

With the regular expressions use it was possible to implement a simplified version of OpenMP to run on GAP8, even with the limitations of systems that deal with MPSoCs. GAP8 has a potential for helps the industry to grow and evolve. Its energy savings can be a solution to the exponential growth of IoTs, more and more devices can benefit from parallel computing without worrying about limiting energy consumption and heat dissipation. Besides that GAP8 provides a offloading from the cluster improving the expected results.

The need to grow technologically is inevitable for the population, which is always seeking information solutions and more and more data are produced. OpenMP can make the development of embedded projects advance and possibly popularize the GAP8 architecture. Translation code level is reached on this work, the goal is to reach the compilation level in addition to include other OpenMP directives. It is hoped that community collaboration will allow this project to grow. Possible inclusion projects of OpenMP interpreters can be included in the compilers of all future platforms.

The results of the translator usage shows a reduction of the codes size, claim less time to a programmer to worry about GAP8 singleness, and enjoying a most known API usage to develop their projects.

This is a work in progress, even with the limitations presented it was possible to notice a considerable decrease in the workload of the programmer. Continuing with this project could give the entire community a contribution and for all those who wish to innovate with performance and low consumption. The target of this job will focus on work in more directives and clauses and reach a compilation level. Potentially, it may increase the adhesion of PULP platform and derivatives projects.

{'source': 'arXiv_out/2007'}