=Paper= {{Paper |id=Vol-2588/paper37 |storemode=property |title=A SIMD-based Approach to the Enhancement of Convolution Operation Performance |pdfUrl=https://ceur-ws.org/Vol-2588/paper37.pdf |volume=Vol-2588 |authors=Andrii Shevchenko,Vitaly Tymchyshyn |dblpUrl=https://dblp.org/rec/conf/cmigin/ShevchenkoT19 }} ==A SIMD-based Approach to the Enhancement of Convolution Operation Performance== https://ceur-ws.org/Vol-2588/paper37.pdf
        A SIMD-based Approach to the Enhancement of
             Convolution Operation Performance

    Andrii Shevchenko 1 [0000-0003-3863-0473] and Vitaly Tymchyshyn 2 [0000-0003-2292-600X]
                          1
                    National Aviation University, Kyiv, Ukraine
                  2
              Bogolyubov Institute for Theoretical Physics, Kyiv, Ukraine
      lllandreyshevchenkolll@gmail.com, yu.binkukoku@gmail.com



        Abstract. Optimization of two-dimensional convolution by means of 16-bit
        SIMD technologies (ARM-NEON) is considered. It is shown that utilizing 16-
        bit SIMD NEON and built-in assembler one can achieve a significant increase
        in performance compared to the similar functions of OpenCV, ACL, and ARM
        Compute library. Throughout the research, ltercoefficients were quantized to
        match the 8-bit range.

        Keywords: Convolution, vectorization, SIMD, optimization, CPU.


1       Introduction

The process of automatic program code vectorization is based on the SIMD instruc-
tions of CPU. It is utilized in modern compilers, e.g. GCC and Clang/LLVM. One can
achieve automatic optimization/vectorization compiling the program with -O3 (or
“aggressive” -O4/-Ofast) flag (actually, flag may differ depending on the platform
and compiler). But as was shown in [1], we often need higher performance for digital
image (DI) processing than we achieve automatically. Moreover, DI problems are of
great importance due to the wide variety of applications in video-stream processing
(stabilization, filtration, noise correction, etc.) and creating different effects for a sin-
gle image. Processing DI, one should always take into account the following features:
   1) computational complexity of the method chosen;
   2) whether the method is optimized;
   3) hardware resources of the target architecture.
    One of the possible ways of computational complexity decrease is to develop a
new particular method for a particular task, e.g. as in [2].
   One can emphasize resource-demanding (but significant) operations of DI pro-
cessing: convolution, scaling (mostly achieved through convolution), and analysis (of
color, brightness, contrast, etc.). Convolution operation (CO) (1) is the simplest but
valuable and resource-demanding operation:
                                                      r    c
                                           pi , j    k ,l Pk  i  a ,l  j  a  ,             (1)
                                                    k 0 l 0




    Copyright © 2020 for this paper by its authors. Use permitted under Creative Commons License Attrib-
ution 4.0 International (CC BY 4.0) CMiGIN-2019: International Workshop on Conflict Management in
Global Information Networks.
where i  a,,W  (r  a)  1 , j  a,, H  (c  a)  1 are indexing pixels of the
destination image p ; W and H are width and height of the source P and destina-
tion p images (we neglect border effects in the destination at the moment),  is the
kernel of the convolution (matrix r  c ), and a , a  - so-called “anchors” that define
relative position of a filtered point within the kernel.
   Equation (1) is rather general and perfectly compatible with cv::filter2D(...) func-
tion of OpenCV library [3] and ARM Computer Library (ACL), but further we will
give our attention to square kernels, i.e. c  r , and thus from now on we presume
kernel to be square-shaped without special mentioning.
   The good part is that every pixel of the destination, at least in principle, can be cal-
culated simultaneously - the task is parallelizable. Parallelizable problems are of such
importance that hardware developers created a set of parallel computing platforms
(PCP): Nvidia CUDA, ATI Stream Technology (ATI-ST), etc., all accessible through
OpenCL API. Every PCP developer provides software toolkit to interact with the
PCP: programming language with C-like syntax, additional modules, frameworks, etc.
Basis for PCPs are modern GPUs that are able to perform in parallel nearly any par-
alellizable task. For example, at the moment GeForce GTX 1080 Ti is very popular
for CNN learning and significantly accelerates the process. One should notice, shader
blocks of GPU are similar to mobile CPUs with RISK architecture that are used in
modern smartphones.
   In conclusion, improvement of CO performance positively affects nearly any soft-
ware on any platform due to the wide variety of tasks it is involved in: DI filtration
(sharpening, edge detection, blurring, etc.), DI scaling, CNN learning, multimedia,
etc. It is worth noting, that CO (1) is the basis for convolutional neural networks
(CNN) functioning. Therefore, accelerating CO we achieve higher CNN performance
and decrease its learning time. Moreover, in some sense CO and similar tasks have
shaped modern approaches to GPU architecture, that emphasizes their importance.
   In current contribution we propose a new method of CO optimization that utilizes
SIMD. Since SIMD can be applied to integer-valued kernels only, we will demon-
strate a reduction method for real-valued kernels that allows this technique to be im-
plied. Besides, we provide experimental comparison of a human-made code based on
this approach with another recognized solutions (OpenCV library, AMD ACL, and
ARM Compute library). The rest of the paper is organized as follows. First, we con-
sider SIMD pros and cons and in subsection II-B we introduce the reduction method
itself.


2      A brief overview of modern software optimization

We will perform the overview in a “bottom to top” style - we consider hardware first,
then software, and then algorithmic methods of performance enhancement.
2.1    Acceleration by means of hardware
Well chosen hardware architecture may significantly enhance software product per-
formance. A general perspective on possible options is given by the Flynn’s taxono-
my [4] and the first question to answer is whether the task (e.g. CO) allows parallel-
ization of data flow or instructions flow. Today SIMD principles are implemented in
both RISC (e.g. Cortex-A8-23 and Cortex-A53-72 ARM CPUs) [5] and CISC (e.g.
Intel x86 series) CPUs. One can access this feature with specific extensions of assem-
bly language - NEON for RISC architecture, while CISC architecture implies SSE n
and AVX1/ 2 usage. In contrast, MIMD principles are not implemented in modern
CPUs, but partially supported by GPUs.
   Modern GPUs provide parallel computing features by means of shader blocks-CPU
(SCPU), based on RISC architecture, that are used in parallel. Principles of MIMD
are achieved by SIMD/MIMD-like instructions for SCPU --- vector instructions for
numerous 128/256/...-bit registers (there are 32 or more registers, that is above the
number that modern CPUs have). The bad part is you cannot access SIMD/MIMD
instructions directly only a small number of intrinsics and pre-implemented opera-
tions are accessible: bit shifts, binary logic, etc. Most cases programmers use specific
frameworks to access mentioned features, e.g. CUDA and OpenCl for GPU, or
OpenCl for CPU/DSP/FPGU. Prevalence of mentioned frameworks led to most GPU
manufacturers get certified by AMD/ATI (compatibility with OpenCl) or Intel/NVidia
(compatibility with CUDA).
   Except using GPU, one can employ co-processor units, e.g. Digital Signal Proces-
sor (DSP). For example, Qualcom has developed DSP-Hexagon for embedding into
Snapdragon-625/635/835/825 CPUs. This DSP provides very long instruction word
(VLIW), which means multithreading at the assembler level - during one interruption
3 assembly instructions with different inputs are processed. Compared to simple
SIMD (NEON32 or NEON64) its performance is 4 times higher. Algorithms, opti-
mized for DSP, reduce CPU load up to ∼ 75% and improve audio/video encod-
ing/decoding performance up to ∼ 18 times [6], [7].

2.2    Optimization by means of software
Software we use to produce binary code (e.g. compiler itself, additional libraries,
frameworks) highly influences program performance by employing different optimi-
zations and hardware platform capabilities. In scope of current article we are mostly
concerned with their ability to perform vectorization without significant loss in preci-
sion. Let's consider three well-known compilers: GNU Compiler Collection
(GCC/G++) [8], Clang [9], and nvcc (compiles cu-files for CUDA).
   Probably, the most popular nowadays is GCC developed and supported by FSF
community. Actually, GCC, first developed by Richard Stallman, is a whole collec-
tion of compilers suitable for different programming languages and architectures. Its
main competitor is the ``rising star'' of compilers - Clang. For example, Apple already
uses it as the basic compiler for its products. Clang itself is a frontend for different
programming languages, e.g. C, C++, Objective-C, Objective-C++, and OpenCL. The
actual generation of binary code and vectorization is performed by the LLVM frame-
work. Both Gcc and Clang are performance-oriented, but still they fail compared to
human-made assembly code (see comparison [1] Clang ndk-r14b vs Inline Assembly
on Android 5.5.1 (x64) phone with CPU-MT6752).
   The last compiler we want to mention is nvcc. It utilizes CUDA and thus allows
significant improvement of performance on platforms with NVidia GPU. But as we
can see, mentioned compilers and technologies introduce large heterogeneity to the
field of program optimization. In a responce OpenCl standard was developed (The
Khronos Group Inc.) that is supported by all mentioned hardware developers and
provides access to parallel computations on GPU/DSP/CPU.
   Except all the advantages of PCPs, they have a drawback - big overhead on trans-
ferring data. To avoid the problem, programmers organize data into pools 100 ∼ 200,
that allows to achieve 20-fold increase in performance compared to CPU. But using
big pools is not always the solution - while CNN learning perfectly fits in this model,
processing stream from video-camera does not at all.
   Except for good choice of compiler, one can achieve performance enhancement us-
ing optimized binary code of frequently used functions like CO, scaling, etc. supplied
by different libraries. Many of them contain SIMD-optimized code for armeaby-v7a
and arm64-v8a. Besides, a collection of libraries can be combined into a single
framework in such a way, that advantages of one library compensate drawbacks of the
others. OpenCV and ACL [10], [11] are good examples of libraries comprising a wide
variety of algorithms, including DI processing, DI analysis, and even module for
CNN learning, that are optimized for different CPU architectures and their SIMD:
 AVX1/ 2 , SSE 4.4 , ARM NEONx32/ x64 . OpenCV is well-known and of a high quality,
but ACL has better extensibility due to modular architecture and seems to perform
better on CO-like tasks (e.g. it is up to ×14 times faster compared to OpenCV on CO
for CNN in one thread [10], [11]). Thus, further we will use both of them as a refer-
ence for comparison.
   At the moment SIMD optimization has spread over the wide range of programming
products, both proprietary and open-source. For example, kernel of Windows 10 uses
 AVX1/ 2 to achieve better performance (obviously, this influences the whole system),
while Oracle Java VM utilizes AVX1/ 2 /3DNow and thus any Java application runs
faster. Game engines of id Tech 2-4 (e.g. the one used in Quake III Arena) are good
example of open-source projects with SIMD optimization. But, using SIMD, they all
face the issue of translating floating-point code to fixed-point with acceptable loss in
precision. This can be quite complicated, thus SIMD optimizations used in proprietary
software are mostly non disclosable.
   One more technique to mention is so-called loop unrolling and tiling [12], [13],
[14], [15] that allows avoidance of redundant comparison operations (e.g. <,>) in cost
of slightly enlargening the code. It is mostly performed by means of compiler or by
introducing appropriate assembly inline-code into the application. Some libraries like
ACL may take advantage of high-level programming language features (e.g. tem-
plates in C++) to perform loop unrolling. A simplified ACL-style code is provided in
listing to demonstrate example implementation (see Помилка! Джерело посилан-
ня не знайдено.).
Fig. 1. Loop unrolling with C++ templates.

Passing appropriate parameters to do_unroll<...>::run(...) from (see Fig. 1), one may
call function f(...) baseStep×unrollDelta+restSteps times avoiding unrollDelta−1
counter comparisons and decrementations. Achieved performance improvement is
discussed in more details in [15].




Fig. 2. CO optimization with SIMD NEON32

2.3    Optimization by means of special algorithms
Instead of rather general consideration as we did previously, let us focus on CO. The
main obstruction for SIMD optimization is translating floating point CO to fixed-
point with acceptable loss of precision. First of all, SIMD operations are performed on
integers only.
  Thus we should represent elements of kernel  from (1) in a suitable form:
                                     i , j   i , j ,   ,  i , j             (2)
where  is a coefficient for normalization. Now we can perform the most resource-
demanding part (additions and multiplications) in a SIMD-style and afterwards nor-
malize the result.
 Any kernel can be represented in form (2), but the more precise result we want the
more digits should  i , j have. At this point we meet limitations of platform on which
we intend to run the program. Thus, we should set some constraints on  to avoid
overflow when doing CO.
  Suppose, every pixel in original image is represented as byte and thus possesses 8-
bit values 0,, 255 . The same range is possessed by kernel elements  i , j . Intermedi-
ate results are stored as 16-bit signed or unsigned values. To warranty that no over-
flow occurs, we should make sure that it does not occur on any step of the algorithm.
If kernel has positive elements only, condition we need looks as follows
                                                r    r
                                    (28  1)    i , j  216  1.                 (3)
                                               i 0 j 0

Substantially, this means that even the largest possible inputs from image do not lead
to overflow.
   If kernel contains negative elements, condition should be much more complicated
and depends on the order of additions when doing CO. Instead, we will use much
stronger but easier to check condition
                                                r    r
                                    (28  1)   | i , j | 216 1  1,            (4)
                                               i 0 j 0

that is independent on the operations order. This condition can be slightly relaxed -
we can use it for positive and negative entries of the kernel  separately. And last
thing to mention: one can easily obtain similar results for signed/unsigned 32-bit in-
termediate values by substituting 16 → 32 in (3) and (4).
   What we propose is selecting for given  the biggest  possible, such that  still
satisfies (3) or (4) (which one depends on whether kernel is purely positive or not). Of
coarse, we should be concerned, whether there exist any useful kernels that can be
reduced to a suitable form. And it seems there are plenty of them.
   In conclusion, modern hardware provides mechanisms for vectorization, i.e. SIMD
technologies, that can be used by programmers to enhance performance of the appli-
cation. Most cases this technology is utilized by compiler to generate binary code
without participation of programmer. Suitable choose of library may be handy as well
- many libraries contain SIMD-optimized code. But in some cases human intervention
is needed to get the most optimal result. Developing assembly code, one should repre-
sent the function in suitable for SIMD optimization form. It is not always possible and
often restrictions (3,4) should be satisfied. In the next section we will provide new
method of CO optimization and then compare it with existing results, e.g. OpenCV
and ARM CL.
Fig. 3. Normalization procedure with SIMD NEON32


3      Optimization of Convolution Operation by means of SIMD

In current contribution we propose a new method of Convolution Operation (CO)
optimization based on SIMD technique. We presume target kernel to satisfy condition
(3). In this section we will provide all necessary considerations and assembly code
that illustrates proposed approach. Next section will be devoted to experimental com-
parison of this method's performance to known CO implementations (OpenCV and
ARM CL).
   Regarding condition (4), provided code should be just slightly modified. We will
avoid redundant listings and provide code considering only condition (3), while at the
end of the section all necessary modification for condition (4) will be described.
We start with basic implementation of CO, (see Fig. 2). It contains no specific optimi-
zations, but still is a good point to start our considerations.
   Here qn are ARM-NEON registers, regarding syntax and instructions order we will
strictly follow ARM reference manuals. For the sake of simplicity we avoided nor-
malization by coefficient  in (see Fig. 2), but for completeness let us provide it as a
separate (see Fig. 3).
   In (see Fig. 3) we suppose data for normalization to be stored in registers q12 …
q15, while d3 contains normalization coefficient  . Presented code is in some sense
multipurpose and may be used with different CO implementations.
   Now we switch gears to the CO optimization itself. In (see Fig. 2) we provided
some initial version of this operation in assembly code. But it has one significant
drawback - slow data loading. Following (see Fig. 4) avoids this problem by using
one of the registers as buffer. It is known, that simultaneous loading of 16 bytes is
quicker than loading them one-by-one (approximately 10 and 40 cycles respectively).
Thus we use one register for preloading extra data and then use this data byte-by-byte
without redundant load operations.




Fig. 4. CO optimization with SIMD ARM-NEON

The main feature of the presented approach (see Fig. 4) is usage of cyclic shift (i.e.
vext.8 q0,q0,q1,\#1) that allows kernel buffering and thus we need less ''loading oper-
ations'' (for more details please see comments in (see Fig. 4). Worth noting, that pro-
vided (see Fig. 4) demands kernel containing not more than 16 elements in one row. If
we need kernels with more than 16 elements in a row, the listing should be just slight-
ly modified.
   As we mentioned earlier, this code works for kernels satisfying condition (3). To
make it applicable to kernels satisfying (4) we need to change all vmlal.u8/u16 opera-
tions to vmlal.s8/s16. This small but crucial changes transform (see Fig. 4) into code
capable of working with signed integer kernels. Depending on given kernel, one can
choose between this two options.
   In conclusion, we found a class of kernels that allow significant optimization of CO
by means of SIMD and were able to implement appropriate code combining ap-
proaches of loop unrolling and method from [13]. Exploiting significant difference in
time for simultaneous 16 byte loading compared to one-by-one loading, we were able
to achieve significant speedup of CO. More detailed results and consideration of
measurement procedure will be presented in the following section.



4      Experimental setup and Results

Ground truth. To evaluate our results certain reference is needed. As the one we chose
functions cv::filter2d(...) from OpenCV library and NEConvolution{N}x{N}::run()
from ACL library. The latter is well-known among AI and DIP researchers due to its
high-quality and optimized code.
   For comparison we used latest stable tags available at the moment we started re-
search, release tags are 4.0.0 (2018-11-18 [11:08:36]) for OpenCV and v19.02 (2019-
02-28 [14:25:18]) for ACL. Compilation was performed with NDK-r18b - latest sta-
ble NDK at that moment for to achieve API capability between them. We ensured that
libraries utilize vectorization compiling them with flags ANDROID_ABI=armeabi-
v7a             with           NEON            ANDROID_NATIVE_API_LEVEL=22
CPU_BASELINE/CPU_BASELINE_FINAL=NEON CPU_BASELINE_FLAGS=-
mfpu=neon -O3 -DNDEBUG. Both OpenCV and ACL were linked as static libraries.
Devices. To make our measurements more relevant we used a set of different devices.
This helps us to understand the influence of architecture, CPU series, and other pa-
rameters on the execution time. Following table lists devices we have used and pa-
rameters of their CPUs.

                    Table 1. Devices that participated in the experiment.

                CPU        Architecture   Series∗           Device
                Exynos 4 armeaby-v7a Cortex-A9 x 4          Samsung GS III
                MT6752     arm64-v8a      Cortex-A53 x 8 Lenovo P70A

Measurement procedure. The pivoting parameter we need to measure is the execution
time of each function. Such measurement might be tricky, since it is highly suscepti-
ble to transition processes in Android OS. To avoid this problem we used the follow-
ing procedure: each function (cv::filter2d(...), NEConvolution{N}x{N}::run(), and
newCO(...)) was successively called 3 times (for robustness and to simulate RGB
processing) and result was stored to array. After collecting 35 data-points we calculat-
ed median value and treated it as trice the execution time of the function under con-
sideration.
   Kernel sizes varied 2×2, 3×3, … , 15×15 for experiments with our implementation
and cv::filter2d(...), while implementation of NEConvolution{N}x{N}::run() necessi-
tates usage of odd-sized kernels only, e.g. 3×3, 5×5, etc. Digital images (DIs) were
generated with equal width and height, corresponding formula follows
                   125 n 
Wimage  H image            32  Wkernel  1, where square brackets […] denote integer
                    8 
part of the number. Results are further presented in form of fractions cv::filter2d(...)
execution time divided by execution time of our implementation and NEConvolu-
tion{N}x{N}::run() execution time divided by execution time of our implementation.
Results. First we compared time consumption of the code (see Fig. 4) and reference
function cv::filter2d(...), result is presented in figures 5a and 5b.




Fig. 5. Performance comparison for different devices and reference functions. Color intensity
designates relative time consumption for reference function with regard to proposed method,
e.g. acceleration one may achieve by using presented approach instead of the reference function
(the brighter is color - the greater is acceleration). Legends on each plot designate how to trans-
late color to acceleration; if this number is greater than 1, it is profitable to use proposed meth-
od.
   As coordinates we use sizes of kernel and image, while color intensity designates
acceleration, one may achieve using proposed method instead of the reference method
(e.g. fraction of execution times: reference function to proposed).
   Despite presented results demonstrate advantage of the proposed method, there is
still room for improvement. It seems, compiler is unable to unroll cycles effectively
on its own,- one may check this by compiling presented code and exploring binary
with any suitable disassembler (e.g. IDA or objdump tool). Thus, we may achieve
additional 30%-40% of acceleration by utilizing techniques [12-13].
   Results for the modified code are shown in figures 5c-5f. We compared time con-
sumption of the (see Fig. 4), modified with approaches [12-13], and both reference
functions (cv::filter2d(...) and NEConvolution{N}x{N}::run()). Besides, we varied
image sizes up to 4500×4500 (~20 [MP]) to emulate modern cameras.
   As (fig. 5) suggests, acceleration is independent (almost) on input size, e.g. com-
plexity (big-O) of our solution and reference solutions coincide. Some small decline
in acceleration (but it is still greater than 1) may be noted for big kernels (9×9 to 15
×15). Regarding mean acceleration, it is estimated as approximately 1.7 times.
   It is worth noting, we did not use parallelism for acceleration. Employing OpenMp
or implementing parallelism by any other means may improve presented results twice
or even more. Moreover, no preprocessing, e.g. image tiling, was performed. Proba-
bly, this technique may increase performance of the approach as well [16-17].


5      Conclusion

In conclusion, we propose a method of convolution operation (CO) acceleration. We
show that many kernels utilized for practical applications can be reduced to integer
form (table I) that allows for SIMD optimization usage. Despite SIMD itself leads to a
significant boost of performance, we were able to push the frontiers even further by
exploiting significant difference in time for simultaneous 16 byte loading (approxi-
mately 10 cycles) compared to their one-by-one loading (approximately 40 cycles) -
q2 register is used as a buffer and loading operations are partially substituted with
cyclic shift (see Fig. 4).
   To test the approach we performed comparison with cv::filter2D(...) function from
OpenCV library and with NEConvolution{N}x{N}::run() from ACL library (fig. 5).
Our results suggest, the current approach leads to significant speedup (mean values:
~1.7× compared to OpenCV and ~1.5× compared to ACL). Measuring acceleration
for different kernels and images we observed no dependence on image size, but kernel
size may influence the result - for kernels smaller than 9×9 we were able to achieve
×4.5 acceleration (compared to cv::filter2D(...) function from OpenCV), while for
larger kernels presented approach allows only ×1.5 speedup. We did not use parallel-
ism in our code, thus additional ×2 or more acceleration is possible by employing
appropriate techniques, e.g. OpenMp library.
   We expect current approach to be useful for real-time image processing and convo-
lutional neural networks training as it significantly reduces processing time.
   References
 1. Chyrkov, A., Prystavka, P.: Suspicious Object Search in Airborne Camera Video Stream. In:
    Hu Z. et al. (eds) Advances in Computer Science for Engineering and Education. ICCSEEA
    2018. Advances in Intelligent Systems and Computing, vol 754, pp. 340–348. Springer,
    Cham, Switzerland (2018)
 2. S. Gnatyuk, V. Kinzeryavyy, M. Iavich, D. Prysiazhnyi, Kh. Yubuzova, High-Performance
    Reliable Block Encryption Algorithms Secured against Linear and Differential Cryptanalytic
    Attacks, CEUR Workshop Proceedings, Vol. 2104, pp. 657-668, 2018.
 3. “Documentation for open-cv,” https://docs.opencv.org/trunk/d4/d86/group__imgproc__filter.
    html#ga27c049795ce870216ddfb366086b5a04, 2017, [Online; accessed 27-November-2017].
 4. M. J. Flynn, “Very high-speed computing systems,” Proceedings of the IEEE, vol. 54, no. 12,
    pp. 1901–1909, 1966.
 5. “Arm® Cortex® - a53 mpcore processor: Reference book of cortex-a53
    cpus,”http://infocenter.arm.com/help/topic/com.arm.doc.ddi0500g/DDI0500G_cortex_a53_tr
    m.pdf, 2013, [Online; accessed 27-November-2017].
 6. “Qualcomm extends hexagon dsp,” http://pages.cs.wisc.edu/~danav/pubs/qcom/ hexa-
    gon_microreport2013_v5.pdf, 2013,[Online; accessed 27-November-2017].
 7. “Qualcomm hexagon dsp: An architecture optimizedfor mobile multimedia and communica-
    tions,”     https://developer.qualcomm.com/download/hexagon/hexagon-dsp-architecture.pdf,
    2013, [Online; accessed 27-November-2017].
 8. Griffith, GCC: the complete reference. McGraw-Hill, Inc., 2002.
 9. B. C. Lopes and R. Auler, Getting started with LLVM core libraries. Packt Publishing Ltd,
    2014.
10. “Presentation of arm-cl,” https://community.arm.com/graphics/b/blog/posts/arm-compute-
    library-for-computer-vision-and-machine-learning-now-publicly-available, 2017, [Online;
    accessed 24-May-2017].
11. “Video presentation for arm-cl,” https://developer.arm.com/technologies/compute-
    library?_ga=2.909169.1792656346.1530630636-1257957724.1521634632, 2017, [Online;
    accessed 24-May-2017].
12. A. Nicolau, “Loop quantization: unwinding for fine-grain parallelism exploitation,” Cornell
    University, Tech. Rep., 1985.
13. J. Xue, “Loop tiling for parallelism, volume 575 of kluwer international series in engineering
    and computer science,” 2000.
14. T. Veldhuizen, “Template metaprograms. c++ report,” 1995.
15. V. Sarkar, “Optimized unrolling of nested loops,” in Proceedings of the 14th International
    Conference on Supercomputing, ser. ICS ’00. New York, NY, USA: ACM, 2000, pp. 153–
    166. [Online]. Available: http://doi.acm.org/10.1145/335231.335246
16. Fedushko S., Benova E. Semantic analysis for information and communication threats detec-
    tion of online service users. The 10th International Conference on Emerging Ubiquitous Sys-
    tems and Pervasive Networks (EUSPN 2019) November 4-7, 2019, Coimbra, Portugal. Pro-
    cedia Computer Science, Volume 160, 2019, Pages 254-259.
17. Gnatyuk S., Akhmetov B., Kozlovskyi V., Kinzeryavyy V., Aleksander M., Prysiazhnyi D.
    New Secure Block Cipher for Critical Applications: Design, Implementation, Speed and Se-
    curity Analysis, Advances in Intelligent Systems and Computing, Vol. 1126, pp. 93-104,
    2020.