Showing posts with label ARM. Show all posts
Showing posts with label ARM. Show all posts

Tuesday, 27 January 2015

The Director of the Centre for High Performance Computing visits Wits electronics lab

The Director of the Centre for High Performance Computing (CHPC), Dr Happy Sithole and the Wits Deputy Vice-Chancellor for research, Prof. Zeblon Vilakazi have visited today the High-throughput Electronics Lab (HTEL) at the School of Physics. Some of our group members currently abroad connected via CERN's vidyo.

Dr. Sithole has shown great interest in the research activities of the students and young researchers of our team. The CHPC is interested in collaborating in the area of high-throughput computing with ARM processors and GPUs. One of the challenges that High-performance computing displays is the ability to move the high volumes of data to performant processors with low latency. The HTEL is devising solutions to this problem based on local designs. The involvement of the HTEL in the upgrade activities of the Tile Calorimeter of the ATLAS detector is a critical driver for these activities.

The function started by introducing Dr. Sithole to the group members and with a presentation about the main activities of the HTEL: FGPA-based electronics, high-throughput general purpose electronics, GPGPUs, ATCA systems, development of low cost computers and electronics radiation, high-throughput data analysis.

Below is a group picture taken at the HTEL. First row, centre, one can see Dr. Sithole, the Head of the School of Physics, Prof. John Carter and Prof. Vilakazi. Missing in the picture are Dr. Deepak Kar, Pablo Moreno, Thokozani Khumalo, Dr. Xifeng Ruan, Dr. Luis March, Shell-may Liao, Guillermo Hamity, Kehinde Tomiwa, the technical support staff and last, but far from least, Prof. Elias Sideras-Haddad.



Prof. Vilakazi addresses the students, referring to the HTEL as a "success story":



The rest of us are happy to listen:


Thursday, 13 November 2014

Press release: LAUNCH OF THE NEW PHYSICS HIGH-THROUGHPUT ELECTRONICS LABORATORY

MEDIA INVITATION FOR PR NEWSWIRE FROM CLIENT WITS UNIVERSITY

ATTENTION: NEWS EDITORS AND SCIENCE REPORTERS

DATE: THURSDAY, 13 NOVEMBER 2014

LAUNCH OF THE NEW PHYSICS HIGH-THROUGHPUT ELECTRONICS LABORATORY

The Wits School of Physics invites all media to the launch of the High-Throughput Electronics Laboratory (HTEL) this Friday, 14 November 2014.
This state-of-the-art new lab and facilities at Wits will be a platform for research and development of high-throughput electronics for the ATLAS detector at the Large Hadron Collider (LHC) at the European Organization of Nuclear Research (CERN). The laboratory is designed to deal with the Big Data problem related to the processing of large amounts of data needed to produce new discoveries, following the observation of the Higgs boson at the LHC.
This work would lead to the massive production of electronic devices by South African industry based on the designs developed at the High-Throughput Electronics Laboratory (HTEL).
Date: Friday, 14 November 2014
Time:  09:30 for 10:00
Venue:  P213 (Honours Presentation Room), School of Physics, Physics Building, Braamfontein Campus East
RSVP: Christina Thinane on 011 717 6848 or Christina.Thinane@wits.ac.za
All media are invited.

About the HTEL:
High-throughput electronics deals with the huge transfer of data at very high rates in challenging environments, such as those with a high level of radiation, possibly event upsets and other factors that may produce data corruption. To “read” this data, very fast decisions need to be made in order to select and modify the large amounts of data at high rates.
This laboratory will first of all serve the needs for upgrade of the ATLAS detector and more specifically, the Tile Calorimeter. This ATLAS sub-detector enjoys strong commonalities in the way data is transferred and how the off-detector electronics are designed.
But it is not only ATLAS that will benefit. South Africa’s flagship big science project, the SKA, also faces the same technological challenges related to high-throughput data flows with fast processing common to that of the ATLAS detector. Prototypes of fast-electronics and computing developed for the ATLAS detector could also be used by the SKA.
A spin-off of the design and prototyping work being done for the ATLAS project is the development of the Massive Affordable Computing (MAC) project. One of the limiting factors for harnessing large computing capabilities is the cost: High-performance computers are not cost-effective and need to be imported to the country. The idea behind this project is to develop prototypes for high-performance computing with cost-effective components for a very wide range of applications in research and industry. 
A first spin-off of the HTEL is the development of a mini-PC, catering to the needs of the educational system of South Africa. Few prototypes are currently available and are being tested at the HTEL. These incorporate power efficient and low-cost technologies. A number of these prototypes will be deployed to schools and universities in January-February for feedback. These mini-PCs could be manufactured in South Africa in quantities large enough to accommodate the needs of the educational system of the country.
Ends
Issued by:
Erna van Wyk
Multimedia Communications Officer | Wits Communications 
University of the Witwatersrand
Contacts: +27 11 717 4023 

Wednesday, 5 November 2014

New NVIDIA Jetson-TK1 Cluster



We recently finished setting up a new cluster, but this time we wanted to go for maximum processing power compared to our existing Wandboard Cluster! We opted for the new NVIDIA Jetson-TK1 development boards which hosts the NVIDIA Tegra K1 System on Chip...

The Tegra K1 is a beast: it has a quad-core ARM Cortex-A15 CPU which runs at up to 2.3 GHz with a fifth low power core which is also a Cortex-A15 except it's clock is limited to a few hundred MHz. There is also a 192 core CUDA (Kepler) GPU on the SoC which, according to the spec sheets, can attain about 350 GFLOPS of performance. Preliminary benchmarks of the CPU indicate that High Performance Linpack scores over 20 GFLOPS in single precision! 

We have built a cluster with 11 boards, which equates to 44 ARM Cortex-A15 cores (~220 GFLOPS), 22 GB RAM, Gigabit Ethernet and around 3850 GFLOPS worth of GPGPU processing power! The entire cluster should consume less than 200 W of electricity under load.

We have started running benchmarks on the cluster and will report the results soon...

Friday, 31 October 2014

Adventures with ARM GCC Auto-Vectorization

I have been experimenting with how well gcc (4.8.2) works with compiling a simple dot product of two vectors with 8 elements in each. I have discovered some interesting things (whether they are bugs or quirks I don't know) and I wanted to share my findings...

The first thing to know is how to generate assembly with gcc. Simply add -S to the gcc or g++ command. I am using Eclipse CDT and I have created several build configurations (some of which generate assembly for inspection).

I have been experimenting with the Eigen Library since it aparently supports ARM NEON. What I found is that it works extremely well with x86 SIMD instructions but not so well with ARM NEON. It seems that well coded C++ is better for NEON that Eigen...

x86 SSE2 with Eigen

movaps      32(%rdi), %xmm0
movaps      16(%rdi), %xmm1
mulps       32(%rsi), %xmm0
mulps       16(%rsi), %xmm1
addps       %xmm0, %xmm1
movaps      %xmm1, %xmm0
movhlps     %xmm1, %xmm0
addps       %xmm1, %xmm0
movaps      %xmm0, %xmm1
shufps      $1, %xmm0, %xmm1
addss       %xmm1, %xmm0

x86 SSE2 without Eigen

movq      (%rdi), %rdx
movq      (%rsi), %rax
movss     (%rdx), %xmm1
mulss     (%rax), %xmm1
movss     4(%rdx), %xmm0
mulss     4(%rax), %xmm0
addss     .LC0(%rip), %xmm1
addss     %xmm0, %xmm1
movss     8(%rdx), %xmm0
mulss     8(%rax), %xmm0
addss     %xmm0, %xmm1
movss     12(%rdx), %xmm0
mulss     12(%rax), %xmm0
addss     %xmm0, %xmm1
movss     16(%rdx), %xmm0
mulss     16(%rax), %xmm0
addss     %xmm0, %xmm1
movss     20(%rdx), %xmm0
mulss     20(%rax), %xmm0
addss     %xmm0, %xmm1

ARM NEON-VFPv4 with Eigen

flds        s0, .L2
ldr         r3, [r1]
ldr         r2, [r0]
flds        s15, [r3]
flds        s14, [r2]
vfma.f32    s0, s14, s15
flds  s6,   [r2, #4]
flds  s7,   [r3, #4]
flds  s8,   [r2, #8]
flds  s9,   [r3, #8]
flds  s10,  [r2, #12]
flds  s11,  [r3, #12]
flds  s12,  [r2, #16]
flds  s13,  [r3, #16]
flds  s14,  [r2, #20]
flds  s15,  [r3, #20]
vfma.f32    s0, s6, s7
vfma.f32    s0, s8, s9
vfma.f32    s0, s10, s11
vfma.f32    s0, s12, s13
vfma.f32    s0, s14, s15

ARM NEON-VFPv4 without Eigen

ldr     r3, [r0]
vmov.f32    q8, #0.0  @ v4sf
ldr     r2, [r1]
vld1.32     {q9}, [r3]!
vld1.32     {q10}, [r2]!
vmul.f32    q10, q10, q9
vst1.64     {d20-d21}, [sp:64]
vld1.32     {q9}, [r3]
vld1.32     {q11}, [r2]
vmov     q12, q10  @ v4sf
vfma.f32    q12, q11, q9
vadd.f32    d18, d24, d25
vpadd.f32   d16, d18, d18
vmov.32     r3, d16[0]

It took quite some effort to get the non-Eigen ARM code to be better then the Eigen code. The "naive" version with a simple dot-product for-loop (shown below) was similar to what Eigen produced. The a and b variables have been __restrict__ed and are pointers to aligned memory.

for (int i = 0; i < 8; i++)
{
    out += a[i] * b[i];
}

The results are not what I would expect. I decided to split these two operations into two separate loops and I got the NEON version shown above! 

float prods[8];

for (int i = 0; i < 8; i++)
{
    prods[i] = a[i] * b[i];
}
for (int i = 0; i < 8; i++)
{
    out += prods[i];
}

I should also add that without -funsafe-math-optimizations, the auto-vectorization doesn't work. I'm going to keep working on it to see if I can shed a few more instructions, but so far so good!

Tuesday, 30 September 2014

HPL Result Comparisons Between Tegra K1 and Other Boards

Hardware Used

Four platforms were used to test various Cortex A Series CPUs. They are described in the table below:


HPL Results

The HPL results shown below are all given in GFLOPS. I included the results at 1GHz for all boards and then at the max frequency. The clock frequencies were as close as possible to 1GHz but the difference was almost negligible. Immediately we notice the Jetson Tegra K1 has approximately 4 GFLOPS more than the Odroid XU+E. This is expected as this is approximately the same ratio as the clock frequency ratio of 2300 to 1600. 
HPL Results for four ARM boards

HPL Efficiency

Similarly to what was done in previous posts I have taken the power measurements of the boards at each frequency and recorded the HPL performance. This gave a nice profile of HPL performance / Watt as a function of clock frequency. The A7 performs fairly poorly but it is a duel core. There are not that many available CPU frequencies on the Wandboard (A9) so we are stuck with just 3 data points but even so we can pretty much see the pattern. The A15-p2 (Odroid, Green) clearly shows the transition between the power saver (Quad A7) and the higher powered A15 which occurs at approximately 600 MHz. The Tegra K1 has a much better power efficiency (Over 2 GFLOPS/Watt at low frequencies). This is impressive but impractical since one would never run these devices at <300 MHz for processing data. What is impressive is that even at 2 GHz the efficiency is still over 1 GFLOPS/Watt.

HPL Squared per Watt

As mentioned in my previous posts the efficiency alone is not that useful. A more interesting feature to look for is the best operating frequency to run these chips to maximise both power consumption and performance simultaneously. This really does give us a nice profile of the boards. It also clearly shows the improvements of the Tegra K1 over the Odroid. What is the main reason is still a little unclear but what we do know is this: The Tegra K1 is a later revision of the Cortex A15. What was changed between the r3p2 and r3p3 revisions is not clear from the ARM website : http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0438g/ch01s08s10.html as all they mention are the register values that are changed and "Various engineering errata fixes". I think a more significant reason is the process type used to manufacture the chips. The Odroid was made with the 28 nm HKMG process and the Tegra K1 was made with the 28HPM process. According to TSMC the 28HPM provides more power will maintaining the same power leakage as the 28LP process.


Friday, 12 September 2014

Characterising the TegraK1 Cortex A15

A Benchmark Characterisation of the Cortex-A15-r3p3

I have run HPL and Coremark from the lowest frequency (204 MHz) to the highest (2.3 GHz). At first I thought the performance per Watt would be interesting but as expected the lower the frequency the lower the power consumption so it only shows that the efficiency is best at 204 MHz. A much more interesting value is the Performance/Watt X Performance. This essentially shows us at which frequency the CPU maximises both the performance and the efficiency simultaneously.

I have done this in the past with the Cubieboard2, Wandboard and Odroid (Cortex-A7-r0p4, Cortex-A9-r2p2, Cortex-A15-r3p2) but I only did it with HPL. I was asked if I had tried this with Coremark. It was simple enough but I wanted to see if I got the same profile shape as HPL. The question arose "how do I compare HPL and Coremark together?". Obviously a direct comparison is not possible as they are fundamentally different benchmarks but we can compare the shapes of the graphs. This can be done by normalising the results so that the area under each graph is equal to 1. The units on the y axis are then expressed in inverse frequency (MHz­­­-1). What we get is shown below.


This is really interesting. This shows that the approach of using the Performance/Watt X Performance does indeed describe the characteristic of the CPU. It also is nice to see that it is similar for both benchmarks. We see for both cases that the optimum frequency is at 1.73 GHz to maximise both Performance and Efficiency. We are in the process of putting together a full set of results into a paper. I will add a link as soon as its finished.

Monday, 8 September 2014

Hands on the New Nvidia TegraK1

Setup to Measure Power Consumption of the TegraK1

I have been benchmarking the Nvidia TegraK1 on our new Jetson development board for the past few days. I am still busy putting together all the results (mostly of the Cortex-A15 r3p3 and not the GPU, just yet) and will post them soon. In the mean time here are some pics of the setup for fun.


Using a small PCB with a 0.01 Ohm resistor (Designed and Built by Mitch) to measure power consumption of the entire board.
If you look closely you can see the results in excel :P (Actually you can't it's showing the Odroid sheet in my excel spreadsheet lol)

Sneak Peak

A quick sneak peak of the power measurements. I used HPL to stress test the boards at different frequencies and measured power consumption. The boards are:
  1. Cortex-A7 = Cubieboard2
  2. Cortex-A9 = Wandboard
  3. Cortex-A15-r3p2 = Odroid XU+E
  4. CortexA15-r3p3 = Jetson TK1




Wednesday, 27 August 2014

Optimal Compiler Flags for ARM

ARM GCC FLAGS

To get a good approximation for the ideal set of gcc flags to use on ARM, COREMARK was compiled and run several times with different flag combinations. I used 16 different combinations with what I assumed were the most important generic flags (Please leave a comment if you know of any other flags I should include!). Below is an example for the Cortex-A7. A similar set of flags was used for the A9 and A15.
Example of flag combinations for the Cortex-A7
I chose coremark for four reasons. One, it is supported by ARM and suggested as the embedded benchmark of choice. Two, it is easily compiled and allows easy configuration. Three, it does not use external libraries so the flags have an affect. Four, the benchmark generates random data during the test so no work is optimised away by the compiler,
Results for different flag combinations for A7, A9 and A15.

Listed below are the flags that were found to be the best. (Generally between 6-10% improvement).

A7    : -O3 -mfpu=neon-vfpv4 -march=armv7-a -mtune=cortex-a7
A9    : -O3 -mfpu=neon         -march=armv7-a
A15  : -O3 -mfpu=neon-vfpv4 -march=armv7-a

A sanity check on my runs found that the iterations I was using in CoreMark was fair for each board. This can be seen by the plateau that is reached by each board. 


Iteration count vs performance. 10s run time was adequate to reach a plateau.


Friday, 28 March 2014

Wandboard PCI-Express Connector PCB Photos

Today I took delivery of the first (and hopefully last if it's bug-free) version of the dual Wandboard PCI-Express adapter. I plan on having it soldered and ready for testing by early next week. Check out the photos!



Wednesday, 12 March 2014

Wandboard PCI-Express Adapter: Update

It's been a while since I last posted about the Wandboard PCI-Express adapter I have been working on... I decided to redesign the PCB to be more compact. This saves manufacturing costs and it looks better, in my opinion.

The PCB has been sent for manufacture so hopefully in a week or two I can post some photos! Shortly after that - assuming everything goes according to plan - I'll post some results for the PCI-Express performance of the Freescale i.MX6 SoC. I don't think the PCI-Express interface to the Wandboard has been tested by anyone, so hopefully it works...



Tuesday, 11 March 2014

NAS Benchmarks on ARM

The NAS Parallel Benchmarks (link) are a comprehensive suite of benchmarks to test supercomputers, maintained by NASA. They were originally based on computational fluid dynamics (in 1994) and expanded over time to cover many different problem types as well as many problem sizes; from very small problems that run in a few seconds for testing purposes, to large problems that can take hours on a supercomputer!

Since these benchmarks cover a range of problems, most interestingly a specific Embarrassingly Parallel benchmark, it is important to test their performance on ARM. Luckily the task of building the benchmark suite on ARM is straightforward. I will document it here for those who are interested. I will write about performance tweaks and compiler flags in a later post once I have had more time to experiment.


Installation (Single Processor Test)

  • Download a copy of the source code from the web site linked above. Unzip the source into a directory on your ARM system.
  • You should already have a full suite of compilers (gcc) installed on your system, as well as MPICH or other MPI library.
  • Navigate into the NPB3.3-MPI directory. Please read the README.install text document for some details. There is a short document in each benchmark directory with some details about that specific benchmark.
  • Navigate into the 'config' directory.
  • Run this command to use the template for the build: cp make.def.template make.def
  • Then run this command to use the template for the suites: cp suite.def.template suite.def
  • You now need to customize the make.def file to your system. Your modifications should be the same as mine if you are running Linux (Linaro) on ARM. Scroll through the file and adjust the lines as below:
MPIF77 = mpif77
FFLAGS = O3
MPICC = mpicc
Un-comment include ../config/make.dummy

  • Note that we uncommented the make.dummy file. This means that true MPI will not be used, and all of the benchmarks will only run with single processor as a simple test.
  • The template suite.def file is fine for this proof-of-concept.
  • Return to the root directory of NAS with ../
  • Type make suite and wait for the build to complete. If something goes wrong there may be an issue with a dependency.

Installation (Multi-Processor MPI)

To install a true MPI version, follow the steps above, except leave the make.dummy commented. You should also modify the suite.def file to suit the number of processors (processes) you would like to run.

To run a multi-processor version type:
mpirun -np 4 ./bin/ep.S.4
For a 4 processor version of EP with a size of S. Obviously the benchmark must be compiled for the correct number of processors. You need to update the command accordingly.

You can selectively compile a single test at a time. Please see the README.install file - it's really quite simple.

Thursday, 6 March 2014

Does the Fused Multiply-Add (FMA) instruction make a difference?

I discussed this originally in my Cortex-A7 FFTW benchmarks, but I am repeating it in it's own blog post for clarity as I believe it's an important thing to understand.

I noticed that when enabling the FMA capabilities of FFTW, the performance actually decreased. I thought to myself "but the ARM VFPv4 supports FMA so this should be faster that doing separate multiply and add operations..." so I did a little bit of research as to why this is the case.

In the computation of an FFT, two of the common operations are:

t0 = a + b * c
t1 = a - b * c

The way that the NEON FMA instruction works, however, is not conducive solving this. This is what happens when you use the NEON FMA instruction:

t0 = a
t0 += b * c
t1 = a
t1 -= b * c

Since ARM is a RISC architecture, the instructions are less flexible and generally take a fixed number of operands. For mathematical operations, it makes sense most of the time to use two operands. Because of this limitation, the FMA can still only take 2 operands and so it is used as shown above. Notice that we have to use up two move instructions for initially setting t0 and t1. It turns out that in this specific case it's faster to just use Multiplies and Adds:

t = b * c
t0 = a + t
t1 = a - t

All in all, the FMA version does 2 Moves, 2 FMA's. The optimal version does 1 Multiply and 2 Adds. It's a small difference, one which the compiler may or may not take note of and optimise, but when done a significant number of times it makes a difference which is what we see in the FFTW benchmarks, for example. There will be cases when this instruction does indeed make a difference, but it's important to bear in mind what's going on behind the scenes.

Thursday, 19 December 2013

FFTW Benchmarks on Cortex-A7

The FFT algorithm has many scientific uses. The most obvious uses are in radio astronomy, for the frequency analysis of signals and is vital to Software Defined Radio (SDR) which is used extensively in the Square Kilometer Array (SKA). In line with the goals of the MAC Project, I am curious about how well an ARM processor (specifically the Cortex-A7) can do FFT - which leads to these benchmarks.

I discovered some existing benchmarks of FFTW done on the Cortex-A8 and A9 by Vesperix here. I used their modified FFTW 3.2.2 for ARM NEON and also ran benchmarks using the latest official version of FFTW: 3.3.3. Both sets of results are presented below with a short discussion afterwards.

I was unable to get the FFTW 3.3.3 NEON version working. I was repeatedly hit by a segmentation fault which I think is due to different memory alignment in the newer NEON and VPPv4 FPU's. I will post these specific benchmarks when the error is resolved.

System Specifications

The tests were run on a Cubieboard2 with the following specifications:
  • Allwinner A20 Dual-Core Cortex-A7 SoC @ ~1GHz
  • VFPv4 and NEONv2 FPU
  • 256 kB L2 Cache
  • 1 GB DDRIII RAM
  • 8GB Class 10 MicroSD Card
  • sunxi kernel 3.4.67+
  • Linaro 13.04 (with GCC 4.7.3)

Benchmark Methodology

I am only presenting the results for a complex 1D FFT with powers of two and non-powers of two. These are the types of FFTs that are most useful to radio astronomy since signal phase and amplitude are represented as a complex number. I ran several sets of benchmarks with various optimisations for comparison, each of which I will describe below.

I first tested the Vesperix FFTW 3.2.2 and then the FFTW 3.3.3. In all cases I used the following configure flags for single precision and the only available timer on the ARM processor:

--enable-single --with-slow-timer

I ran non-SIMD (no NEON) test without any extra flags, and NEON SIMD tests with the flag below:

--enable-neon

I also tried out the fused multiply-add flag since the Cortex-A7 has this instruction in the VFPv4 FPU but I found that this flag actually caused performance to decrease! A short description of why this is can be found in the FFTW 3.3.3 tests section.

--enable-fma

In all cases I modified the configure script to optimise for the CPU with the '-mcpu=cortex-a7' flag. I also modified the configure script to try out different GCC FPU options where appropriate, but in general I am only presenting the fastest results in this post. The options I tried are listed below for reference:

-mfpu=neon
-mfpu=neon-vfpv4
-mfpu=vfpv4-d16
-mfpu=vfpv3-d16

I repeated the tests with NEON on a threaded version of FFTW to see at which point multiple threads (on multiple cores) makes a difference and by how much. To enable the threaded version, FFTW must be recompiled with the flag below. Note that FFTW can be compiled once with this flag and used in both a threaded or unthreaded way.

--enable-threads

I plan on running an MPI version with more threads (4 to 16) on our Cubieboard and Wandboard clusters at a later stage.

I used the script provided by Vesperix to automate the benchmarks. For the threaded tests I modified the script to contain the '-onthreads=2'. The number can be adjusted to suit the number of cores available on the system. The modified script is shown below.

#!/bin/sh
for TYPE in 'c'; do
  for PLACE in 'i' 'o'; do
    echo "$TYPE $PLACE 1-D powers of two (2 threads)"
    for SIZE in '2' '4' '8' '16' '32' '64' '128' '256' '512' '1024' '2048' '4096' \
                '8192' '16384' '32768' '65536' '131072' '262144' '524288' '1048576' '2097152'; do
      ./bench -onthreads=2 $OPTS ${PLACE}${TYPE}${SIZE}
    done
  done
  for PLACE in 'i' 'o'; do
    echo "$TYPE $PLACE 1-D powers of two (1 thread)"
    for SIZE in '2' '4' '8' '16' '32' '64' '128' '256' '512' '1024' '2048' '4096' \
                '8192' '16384' '32768' '65536' '131072' '262144' '524288' '1048576' '2097152'; do
      ./bench $OPTS ${PLACE}${TYPE}${SIZE}
    done
  done
done

MFLOPS Result Interpretation:

The result provided by FFTW is 'MFLOPS': this is not true MFLOPS. It is estimated by FFTW based on an assumption of algorithmic complexity for the standard Cooley-Tukey FFT algorithm:

Although not necessarily totally accurate in the classic FLOPS sense, it is calculated the same way in all cases, so it works as a way to compare between runs. For comparison to other algorithms, I would rather use the actual time the algorithm takes to run on a specific FFT size (N).

FFTW 3.2.2 (Vesperix):

Please examine the various graphs below. Clearly, NEON makes quite a large difference and is a 'no-brainer' for any application. I am showing one set of non-power of two benchmarks to illustrate why they should not be used.



I ran a test of the threaded version of FFTW 3.2.2 and the results are promising for a scaled-up system. The Cubieboard2 is only a dual-core system but I plan on running MPI tests with more cores at a future date.



FFTW 3.3.3 (Official):

I was unable to get the NEON version of FFTW 3.3.3 working. I was able to run benchmarks of the scalar version of the code which shows a performance improvement over the 3.2.2 scalar results. I compiled one graph comparing all the different scalar versions, with FMA instructions and without.



Note how the FMA versions have slightly lower performance. In the Benchmark Methodology section I mentioned that the --enable-fma flag actually causes performance to decrease. The reason for this is not intuitive as one would think that a Fused Multiply Add (FMA) instruction would save cycles as it replaces separate Multiply and Add instructions. In the computation of an FFT, two of the common operations are:

t0 = a + b * c
t1 = a - b * c

The way that the NEON FMA instruction works, however, is not conducive solving this. This is what happens when you use the NEON FMA:

t0 = a
t0 += b * c
t1 = a
t1 -= b * c

Notice that we have to use up two move instructions for initially setting t0 and t1. It turns out that in this specific case it's faster to just use Multiplies and Adds:

t = b * c
t0 = a + t
t1 = a - t

All in all, the FMA version does 2 Moves, 2 FMA's. The optimal version does 1 Multiply and 2 Adds. It's a small difference, one which the compiler may or may not take note of and optimise, but when done a significant number of times it makes a difference.

Conclusion

The results from this set of benchmarks are very similar to those attained by Vesperix on Cortex-A9 boards. The multi-threaded version is also significantly better for larger FFT sizes. The results at different FFT sizes are very dependant on the processor implementation details such as cache sizes and memory access times. With smaller FFT's the overhead associated with calculating the FFT is a large factor and this is clearly visible up to sizes of 128.

The scalar results for FFTW 3.3.3 are better than those from 3.2.2 so it is logical to assume that the newer version's NEON performance will be better as well.

Since FFTW works by creating a 'plan' before actually calculating the FFT, it chooses to not use more than one thread in the multi-threaded version before a certain FFT size. This is clearly visible as it chooses to use multi-threading at greater than size 128. The overhead associated with doing this causes the result to be poor at size 256 and based on the results, multi threading should only be enabled for sizes over 1024.

The power usage of the Cortex-A7 processor is lower than that of the Cortex-A9 and so if a large cluster of these devices is used for a computational task such as radio astronomy, one could speculate that it may be worthwhile to use more Cortex-A7's over fewer Cortex-A9's since the performance is similar. 


Wednesday, 4 December 2013

Wandboard PCI-Express Adapter: Preliminary PCB 3D Images

I have been designing an adapter board to connect two Wandboards via their PCI-Express ports. The design will be finished by the end of this week, after which it will be sent in for manufacturing! This post is simply to show off two quick 3D renderings of the boards so far.

We will use this board for testing and benchmarking the potential throughput of the Freescale i.MX6 processor. The gigabit ethernet on the i.MX6 is limited to ~400 Mbps according to the datasheet, but we should be able to attain close to 5 Gbps with extremely low latency using the PCI-Express Gen 2 x1 port!

More details will follow when the board has been manufactured and tests are complete!




Saturday, 30 November 2013

Complete Wandboard Array

Following the previous posts regarding the installation of HPL on the Wandboard and Cubieboard2 and the subsequent setup of the two Cubieboards connected and running HPL I am pleased to share that we have set up five Wandboards running Ubuntu 13.05 Server (Thanks to Martin Wild) and using MPICH2 as the MPI.

If you would like details on how to set up multiple boards please view my post of setting up the Cubieboard2 "array" here.

Getting things ready


The Wandboards arrived with out power adapters. We decided to build our own using a normal PC 300W power supply as this provides proper grounding and if there are static discharges against the boards they will be better protected.

Here is the first power connector we made. The green strip is a small two channel PCB board.
 The cable is standard two core cabling with a plug at the end which fits the Wandboard sockets. I used extra long spacer screws so that we could stack the boards on top of each other. They had to be spaced wide enough that the heat wouldn't be an issue and so that we could get fingers at each board in case we need to add hard drives.

Stacked array of the Wandboards

Now before connecting the power I had to write pre-made images to the sd card for each board Once I had one board up and running I then copied the SD card to the remaining four and set each IP address. There were a few issues with this which ill speak about at the end. Once the board were all up I connected everything together.

Completed Array


Wandboard array with power and Ethernet
 Now following similar procedures as my previous posts I set up HPL over a shared drive using NFS and I configured the HPL for neon and hardfp. I ran a quick test on the array using a small problem to test if all boards would indeed respond correctly. I was happy to see that all five boards showed xhpl in the processes (top) when I ran HPL.

Five terminals showing active processes when running HPL

Next up


I tried to compile ATLAS for the Cubieboard2 using neon-vfpv4 but the compiling got stuck at the L1 cache due to an infinity popping up somewhere. I will recompile that using just neon and do something similar for the Wandboard. This will improve performance quite a lot as I am using a standard ATLAS library at the moment. Once that is done I will be able to start tuning the HPL.dat file for the array.

Problems Encountered


An interesting problem came up when I copied the OS from one SD card to the other. During boot it would take exceptionally long and after finally starting up there would be no Ethernet. I checked for the adapters using ifconfig -a and they were named eth1 or eth2... not the default eth0. After doing some investigating it was quite obvious... When Linux boots up it searches for the devices and saves them in the following file:

/etc/udev/rules.d/70-persistent-net.rules

Since the hardware was changing it was appending the new hardware to the end of this list. Thus the system searched for the first one and then moved onto the next. Simply removing the content and restarting solved this issue.

Another issue was the locals. I am not sure why this one popped up but after some reading through some material I just generated the locale and reconfigured it. Using the following commands:

sudo locale-gen fi_FI.UTF-8
sudo dpkg-reconfigure locales

Sunday, 24 November 2013

Set up "Array" of two Cubieboard2's with MPI and HPL

Now that I have been able to get HPL working on the Cubieboard2 the next step would be to get it working on an array of boards. I was only able to get my hands on two boards so I am treating this as a proof of principle for later larger arrays.

If you do not have HPL set up on your board and would like a walk through please see my previous post: Installing HPL on Cubieboard2

Before we start. This is the setup I am using: Two Cubieboard2 running Ubuntu 13.10. Each board has one CPU and 2 cores with 1GB DDR3 RAM. In total we have 4 cores and 2GB RAM. I have called the boards cubiedev1 and cubiedev2 (Host names). OK lets get started.

MPI needs to be able to identify the nodes (actual machines or computers) so that it can execute the programs on each of the nodes cores. to do this we need to set up a hosts file.

Host names on Master Node

On the master node (Generally the node where you will issue the tests and store results) edit the host names file and add in the corresponding computers with their designated IP's. 

nano /etc/hosts

127.0.0.1 localhost
192.168.1.1 cubiedev1
192.168.1.2 cubiedev2

Note that you must not have the master node specified as localhost. I.E. You must not have 127.0.0.1 cubiedev1... Even if this is true for this board it will cause the other nodes to try connect to localhost when connecting to cubiedev1.

Using NFS for Ease of Testing

NFS allows you to mirror a hard drive over the network. This is extremely useful for us since to run a program such as HPL, the exact same version must be installed on all of the nodes. So instead of copying the program to all nodes we can mirror the drive and then do all our editing once and not have to worry about distributing the program around. 

To install run:

sudo apt-get install nfs-kernel-server

Now we need to share the folder we will work in... The sd card that the cubieboard has its OS on is only 8GB. I have an external HDD mounted in the directory /mnt/cub1/ if you want to mirror a folder on your sdcard its not a problem but the r/w speeds are generally not that great and you are limited by the size. So I created a directory called mpiuser on /mnt/cub1/ and I will run all my tests from this folder.

So now we have the directory /mnt/cub1/mpiuser and we must edit the folder exports and add the directory and restart the nfs service.

nano /etc/exports

/mnt/cub1/mpiuser *(rw,sync)
sudo service nfs-kernel-server restart

The folder mpiuser has now been shared but we need to mount this on the other nodes and link it to the master node. We can do this manually from the terminal each time we boot with the mount command or we can edit the fstab file so it mounts at boot.

nano /etc/fstab

cubiedev1:/mnt/cub1/mpiuser    /mnt/cub1/mpiuser    nfs

sudo mount -a
repeat on each node

Creating the user for all MPI programs

Creating one user with the same name and password on each board will allow us to easily access each node over ssh. We need to create the user and set the home directory to our shared folder mpiuser. We then also need to change the ownership of the folder to this user.

sudo adduser mpiuser --home /mnt/cub1/mpiuser  
sudo chown mpiuser /mnt/cub1/mpiuser 

Make sure that the password is the same on all boards.

Configure SSH to use keys and not passwords

Change to our new user:
su - mpiuser

Create the key using
ssh-keygen -t rsa

Use the default location as this is now a shared directory and will update to all nodes.
Now we need to add this key to the authorized keys:
cd .ssh  
cat id_rsa.pub >> authorized_keys

If you can ssh into the other nodes using their host names then you have set it up correctly. Test using:
ssh cubiedev2

MPI software

I have already installed the MPICH2 for my MPI program as I did this in the previous post mentioned before. You can use OpenMPI. It's up to you. 

We need to set up a machine file. This file will be a flag when running using the mpi command. It is a list of hosts with the specified number of nodes that you want to use. An example of the machines file that I have is:

cubiedev1:2 #The :2 represents the number of cores
cubiedev2:2

To test if this works we will use a simple test script which can be found on this blog. Save the content below to a file called mpi_hello.c

#include 
#include 

int main(int argc, char** argv) {
    int myrank, nprocs;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank);

    printf("Hello from processor %d of %d\n", myrank, nprocs);

    MPI_Finalize();
    return 0;
}

Compile it with
mpicc mpi_hello.c -o mpi_hello

Now run it with the correct number of specified processors (1 for each core)
mpirun -np 4 -f machines ./mpi_hello

The output I get is:
Hello from processor 0 of 4
Hello from processor 1 of 4
Hello from processor 2 of 4
Hello from processor 3 of 4

Cool... Now we know that all the processors are being "seen".

Set up the HPL files

Copy the HPL files that you have been using into the mpiuser directory on the shared hdd. Make sure the ower is set correctly via the chown hpl mpiuser command. If you are unsure of how to set up HPL please see Installing HPL on Cubieboard2

Set the HPL.dat file so that the product of P x Q = 4 (since we running it on both cubieboards) also make sure your problem size is large enough.

Now run HPL using:
mpirun -np 4 -f machines ./xhpl

Friday, 15 November 2013

Benchmarking of ARM processors with CMS software

CMS colleagues have recently reported benchmarking of ARM processors with CMS software. Interesting and promising results:

http://arxiv.org/pdf/1311.0269v1.pdf

Installing HPL on Cubieboard2 + Ubuntu 13.10

I am following almost exactly the same procedure as my previous post with Ubuntu 12.04. Here we are working with Ubuntu 13.10 Server on the Cubieboard2 which can be found here: http://www.cubieforums.com/index.php/topic,891.0.html

System Specs

  • Cubieboard 2
    •  Processor         - Allwinner A20
    •  Cores               - Cortex-A7 Dual core
    •  Graphics PU      - ARM® Mali400MP2
    •  Memory           - 1GB DDR3
  • Using Ubuntu 13.10 Server
    • This version uses hardfp which is more suited for the arm and makes use of the VFP
    • The GCC compiler for 13.10 is more updated than 12.04. We have 4.7

Prerequisites

HPL requires the availability of a Message Passing Interface (MPI) and either the Basic Linear Algebra Subprograms (BLAS) or Vector Signal Image Processing Library (VSIPL). In my case I have used MPICH2 and the ATLAS package both of which I got from the repository. Before you start thinking why I have not used an ATLAS tuned BLAS and that my results will be poor because of it I remind you that my main objective is to have HPL up and running first and foremost. There are too many things that can go wrong in the ATLAS tuned BLAS approach. I will however get to these topics in future posts.

Get the required packages

sudo apt-get install mpich2
sudo apt-get install libatlas3-base-dev

Then get the HPL source code from http://www.netlib.org/benchmark/hpl/hpl-2.1.tar.gz
And extract it to a folder in your home directory. We need to produce the generic make file and then edit this according to our system.

Now to install

tar -xvf hpl-2.1.tar.gz
cd hpl-2.1/setup
sh make_generic
cp Make.UNKNOWN ../Make.cubieboard

Now you must link your MPI libraries correctly in order for the build to incorporate multi core support. It took me a few hours of changing things around till I got it working. This is what I had to change in the end.

ARCH       = cubieboard
TOPdir     = $(HOME)/HDD/hpl-2.1
MPdir      = /usr/lib/mpich2
MPinc      = -I$(MPdir)/include
MPlib      = /usr/lib/libfmpich.a
LAdir      = /usr/lib/atlas-base/
LAlib      = $(LAdir)/libf77blas.so.3 $(LAdir)/libatlas.so.3
HPL_LIBS   = $(HPLlib) $(LAlib) $(MPlib) -lmpl -lcr
CCFLAGS    = $(HPL_DEFS) -mfpu=neon -mfloat-abi=hard -funsafe-math-optimizations -ffast-math -O3

Just make sure you use the correct TOPdir and if you have your libraries in different locations then change the above accordingly. I added the CCFLAGS as I wanted the best results (knowing I have standard BLAS libraries). Here is my entire make file if you would like to compare Make.cubieboard-U13.10 .

Now compile HPL

make arch=cubieboard

HPL has a large amount of input variables and an even large combination of them that can be very intimidating. I still have not wrapped my head around all of them. If you go into the HPL.dat file you will see what I mean. You can find it in the bin/cubieboard/ folder. You can find a full explanation of what the input variables do here. A very useful site I found gives you a standard HPL.dat file to start from. So lets start by going to the site and filling out the specs you need. Below is the HPL.dat file that I used.

HPLinpack benchmark input file
University of the Witwatersrand
HPL.out      output file name (if any)
8            device out (6=stdout,7=stderr,file)
1            # of problems sizes (N)
8000         Ns
1            # of NBs
128           NBs
0            PMAP process mapping (0=Row-,1=Column-major)
1            # of process grids (P x Q)
1            Ps
2            Qs
16.0         threshold
1            # of panel fact
2            PFACTs (0=left, 1=Crout, 2=Right)
1            # of recursive stopping criterium
4            NBMINs (>= 1)
1            # of panels in recursion
2            NDIVs
1            # of recursive panel fact.
1            RFACTs (0=left, 1=Crout, 2=Right)
1            # of broadcast
1            BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM)
1            # of lookahead depth
1            DEPTHs (>=0)
2            SWAP (0=bin-exch,1=long,2=mix)
64           swapping threshold
0            L1 in (0=transposed,1=no-transposed) form
0            U  in (0=transposed,1=no-transposed) form
1            Equilibration (0=no,1=yes)
8            memory alignment in double (> 0)
##### This line (no. 32) is ignored (it serves as a separator). ######
0                               Number of additional problem sizes for PTRANS
1200 10000 30000                values of N
0                               number of additional blocking sizes for PTRANS
40 9 8 13 13 20 16 32 64        values of NB

Note that you must specify the number of cores that you want to run on. So in our case here the Cubieboard2 is a dual core hence we specify Ps X Qs = 1 X 2 = 2. If you wanted to run this on a single core then you would set Ps = Qs = 1. If you do not have the correct number of cores then you will get an error when running HPL. Note that if you run multiple process grids then you must start HPL with the maximum number of cores that are needed.

Now to start HPL on both cores I need to run the mpi command. This is done with

mpirun -np 2 ./xhpl

The -np determines the number of cores. This must be the same as the product Ps X Qs. The output is then piped to the file HPL.out

Next Up

This was largely successful as it proves that the HPL is working on both cores. The next steps will be to custom tune the BLAS libraries and also optimise the OS with better configured Kernels. This will be explain in a different post by Mitch.


Building a Cubieboard Kernel: Part 1

To date it seems that all of the pre-compiled kernels and toolchains online for the Cubieboard are using stock parameters which tend to be tuned for the Cortex-A9 or built using an older version of GCC which does not fully support the Cortex-A7 CPU!

For these reasons, and also because I would like to make a more 'Lean and Mean' kernel with less pointless drivers to waste memory, I have endeavoured to build my own. This post will describe the general process of building a kernel for the Cubieboard. I will note a few initial changes I made to the kernel config but there needs to be some testing before I can conclude whether my changes (and more to come, I'm sure) are worth it or not. I plan on making a 'Part 2' to confirm performance changes and my final kernel config.

Let's Get Started!

The first step is to ensure you have a working cross-compiler toolchain installed. If you do not, see my post here on setting up the latest Linaro toolchain. This post describes how to modify this toolchain to be more optimised for the Cortex-A7.

Besides the toolchain setup, above, please make sure you have u-boot-tools installed:

sudo apt-get install u-boot-tools

This package contains the mkimage command that is required to make the final image. You then need to get the source code. Kernel sources tend to be huge so I opted to get only the latest revision of code and no history. I think this at least halved the download size!

git clone --depth 1 https://github.com/linux-sunxi/linux-sunxi.git --branch sunxi-3.4

This was about a 400 MB download. Once it completes, there is a handy command to load an initial working config for the Cubieboard:

make ARCH=arm CROSS_COMPILE=${CC201310A7} sun7i_defconfig


Some Config Changes

If you would like to view or modify this default configuration then you can get to the normal menuconfig with:

make ARCH=arm CROSS_COMPILE=${CC201310A7} menuconfig

This will bring up the classic Linux kernel menuconfig. Here you can browse through, see some info on the various items with the help command, and change things! Be sure to save the config when you are done: there is a save option near the bottom of the main menu. Save the config as .config for it to be used by the make command.

As I mentioned earlier I chose to modify a few things in this initial run. I plan on comparing the performance between the kernels supplied by the community, a kernel that is a stock configuration but compiled for the Cortex-A7 with GCC 4.8 and also a kernel with my modifications to the config.

Initially, I chose to only turn of forced preemption, which should allow higher throughput by telling the kernel to not jump through tasks too quickly. The default was set to a real-time system which is great for desktop, but not great for processing tasks. Here's how you find the setting:

Kernel Features -> Preemption Model -> No Forced Preemption


Another issue I discovered was that by default, the ethernet drivers are not compiled into the kernel - they are build as a module. This means that to use the module we have to manually tell Linux to load it. I don't want this behaviour, so I specified to build the ethernet drivers into the kernel.


Note that to get ethernet to work after you first boot, later on in the process, you will probably have to tell the system to bring up the interface and add some stuff to the config files so that this happens on boot:

ifconfig eth0 up
echo auto eth0 >> /etc/network/interfaces
echo iface eth0 inet dhcp >> /etc/network/interfaces

The Build

Once you are happy with your changes you can build the kernel. Modify the -j3 to -j(number of CPU's + 1) to suite your build system for a faster build.

make ARCH=arm CROSS_COMPILE=${CC201310A7} uImage modules -j3

and then

make ARCH=arm CROSS_COMPILE=${CC201310A7} INSTALL_MOD_PATH=output modules_install

This will take a while... Once it's done you only need to copy the kernel uImage and modules onto your SD card! The commands below will do this for you. Note that I have mounted the boot partition of my SD card to /media/boot and the rootfs to /media/rootfs. If the uImage file is missing then the compile above failed at some point.

sudo cp -v arch/arm/boot/uImage /media/boot/
sudo rm -r /media/rootfs/lib/*
sudo cp -rv output/* /media/rootfs/lib/

Unmount the SD card, put it in your Cubieboard and hope for the best! ;)