comp.lang.ada
 help / color / mirror / Atom feed
From: darek <darek.maksimiuk@gmail.com>
Subject: GNAT vs Matlab - operation on   multidimensional complex matrices
Date: Mon, 23 Mar 2020 16:16:18 -0700 (PDT)
Date: 2020-03-23T16:16:18-07:00	[thread overview]
Message-ID: <6c2c0e35-af07-4169-8be5-464ec7fd0fd5@googlegroups.com> (raw)

Hi Everyone, 
 I am working on radar signal processing algorithms that use multidimensional complex arrays. 

To my surprise, the performance of some Matlab functions is much better than compiled Ada code. 

Let's start with a simple problem of computing sum of all elements in a 3D real and complex array. 

The Ada code is as follows:

with Ada.Text_IO;
with Ada.Real_Time; use Ada.Real_Time;
with Ada.Unchecked_Deallocation;

with Ada.Numerics.Long_Complex_Types;  use Ada.Numerics.Long_Complex_Types;

with Ada.Text_IO.Complex_IO;

procedure TestSpeed is
   

   
   package TIO renames Ada.Text_IO;
   
   package CTIO is new Ada.Text_IO.Complex_IO(Ada.Numerics.Long_Complex_Types);
   
   subtype mReal is Long_Float;
   
   
   NumIteration : constant := 1_000;
   NumChannels  : constant  := 64;
   NumRanges    : constant  := 400; 
   NumAngles    : constant  := 30;
   
   type tCubeReal is array (1..NumChannels, 1..NumAngles, 1..NumRanges) of mReal;
   type tCubeRealAcc is access all tCubeReal;
   --for tCubeReal'Alignment use 8;
   
   type tCubeComplex is array (1..NumChannels, 1..NumAngles, 1..NumRanges) of Complex;
   type tCubeComplexAcc is access all tCubeComplex;
   --for tCubeComplex'Alignment use 16;
   
   RealCubeAcc : tCubeRealAcc;
   SReal       : mReal;
   
   ComplexCubeAcc : tCubeComplexAcc;
   SComplex    : Complex;

   
   procedure Free is new Ada.Unchecked_Deallocation(tCubeReal, tCubeRealAcc);
   procedure Free is new Ada.Unchecked_Deallocation(tCubeComplex, tCubeComplexAcc);
   
   --| -------------------------------------------------------------------------
   procedure SpeedSumRealCube (NumIteration : Integer; Mtx : in  tCubeReal;  S: out mReal) is
      
      Ts   : Time;
      TEx  : Time_Span; 
      t    : mReal;
   begin
      Ts := Clock;
      S := 0.0;
      for k in 1..NumIteration loop
         for m  in Mtx'Range(1) loop
            for n in   Mtx'Range(2) loop
               for p in   Mtx'Range(3) loop
                  S := S + Mtx(m, n, p);
               end loop;
            end loop;
         end loop;      
      end loop;

      TEx :=  Clock - Ts;
      TIO.New_Line;
      TIO.Put_Line("Computation time:" & Duration'Image(To_Duration(TEx)));
      t := mReal(To_Duration(TEx))/mReal(NumIteration);
      TIO.Put_Line("Computation time per iteration:" & t'Image);
   end SpeedSumRealCube;
   
   --| -------------------------------------------------------------------------
   
   procedure SpeedSumComplexCube (NumIteration : Integer; Mtx : in  tCubeComplex;  S:  out Complex) is
      
      Ts   : Time;
      TEx  : Time_Span; 
      t    : mReal;
   begin
      Ts := Clock;     
      S := 0.0  + i* 0.0; 
      for k in 1..NumIteration loop
         for m  in Mtx'Range(1) loop
            for n in    Mtx'Range(2) loop
               for p in   Mtx'Range(3) loop
                  S := S + Mtx(m, n, p);
               end loop;
            end loop;
         end loop;      
      end loop;
      TEx :=  Clock - Ts;
      TIO.New_Line;
      TIO.Put_Line("Computation time:" & Duration'Image(To_Duration(TEx)));
      t := mReal(To_Duration(TEx))/mReal(NumIteration);
      TIO.Put_Line("Computation time per iteration:" & t'Image);
   end SpeedSumComplexCube;
   
   --| -------------------------------------------------------------------------
   
begin
   TIO.Put_Line("Real cube");
   TIO.Put_Line("Real type size is:" & Integer(mReal'Size)'Image);
   RealCubeAcc := new tCubeReal;
   RealCubeAcc.all := (others =>(others =>( others => 1.0)));
   SpeedSumRealCube(NumIteration => NumIteration,
                    Mtx           => RealCubeAcc.all,
                    S            => SReal);
   
   TIO.Put_Line("Sum is:" & SReal'Image);
   
   TIO.Put_Line("Complex cube");
   TIO.Put_Line("Complex type size is:" & Integer(Complex'Size)'Image);
   ComplexCubeAcc := new tCubeComplex;
   ComplexCubeAcc.all := (others =>(others =>( others => 1.0 + i * 1.0)));
   SpeedSumComplexCube(NumIteration => NumIteration,
                       Mtx          => ComplexCubeAcc.all,
                       S            => SComplex);
   
   TIO.Put("Sum is:"); CTIO.Put(SComplex);
   Free(ComplexCubeAcc);
   Free(RealCubeAcc);   
end TestSpeed;

1. Compiled with:  gcc version 9.2.0 (tdm64-1) ( and gnat community edition 2019), with the -O2 optimisation level. 
2. CPU: AMD64 Family 23 Model 24 Stepping 1  CPU0      2300           AMD Ryzen 7 3750H with Radeon Vega Mobile Gfx
3. Win10 64bit 


The results of the program execution:

Computation time: 0.616710300
Computation time per iteration: 6.16710300000000E-04
Sum is: 7.68000000000000E+08
Complex cube
Complex type size is: 128

Computation time: 3.707091000
Computation time per iteration: 3.70709100000000E-03
Sum is:( 7.68000000000000E+08, 7.68000000000000E+08)


The executable produced by the gcc provide with the gnat community edition gave very similar results.

More interesting part - the Matlab code.

Matlab version : Matlab 2019b, 64bit

function [] = TestSpeed 

NumIterations = 1000;
NumChannels = 64;  
NumRanges  = 400; 
NumAngles = 30;

%--| real matrix 

ReMtx = ones(NumChannels, NumAngles, NumRanges);

tic
SReal =  ComputeSum(NumIterations, ReMtx);
TExR = toc;%cputime-ts;
fprintf('TExe:%f, sum real=%f\n', TExR, SReal);
%--| complex matrix
CplxMtx = complex(ReMtx, ReMtx);
%ts = cputime;
tic
SCplx = ComputeSum(NumIterations, CplxMtx);
TExC = toc; %cputime - ts;
fprintf('TExe:%f, sum complex= <%f,%f> \n', TExC, real(SCplx), imag(SCplx));
fprintf('Complex operations are %f times slower\n', TExC/TExR);
end % function


function [S] = ComputeSum(NumIterations, Mtx)
 S = 0;
 for i = 1:NumIterations   
    S = S + sum(sum(sum(Mtx)));  
 end % for  
end % function 

The results of the program execution:

TExe:0.260718, sum real=768000000.000000
TExe:0.789778, sum complex= <768000000.000000,768000000.000000> 
Complex operations are 3.029242 times slower


What is wrong with my code ? Is it the Ada compiler doing bad job here?
 
If you look at Matlab code, on average the computation that use complex  addition are ~3 times slower than for the real numbers.

In the case of Ada code, the complex operations are ~ 6 times slower that for the real numbers. 

Did I miss something somewhere ? Any ideas how I can improve the performance of the Ada program (different array layout, magic pragmas, or magic compiler switches) ?

It seems that Matlab is performing really well here ...

Any suggestions are  very welcome.

Regards,
  Darek  







             reply	other threads:[~2020-03-23 23:16 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-23 23:16 darek [this message]
2020-03-24  2:07 ` GNAT vs Matlab - operation on multidimensional complex matrices johnscpg
2020-03-24  6:40 ` J-P. Rosen
2020-03-24  9:37 ` Jeffrey R. Carter
2020-03-24 14:55   ` darek
2020-03-24 15:44 ` johnscpg
2020-03-31 17:25 ` Shark8
2020-03-31 19:20   ` Simon Wright
2020-03-31 19:54     ` Shark8
2020-04-29 21:08     ` vincent.diemunsch
2020-04-01 11:01   ` darek
2020-04-01 15:01     ` J-P. Rosen
2020-04-01 16:39       ` darek
2020-04-01 17:15         ` J-P. Rosen
2020-03-31 20:05 ` Shark8
2020-03-31 20:51   ` Jeffrey R. Carter
2020-06-08 17:42 ` Shark8
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox