Extremely fast x86_64 library

Wanted to let you know about this extremely fast (faster than C) and very small library (1.2Mb), most of the time giving you 200% increase over C code and for some functions even an order of magnitude! The speed comes because the whole library is written in (very well done) assembly using simd.

You call the library from regular C functions as it provides .h headers.

It has functions for arrays, strings, number conversion, trees, statistics, math, 2d and 3d vectors, matrices, linear approximations and more. It it really a little unknown gem for those working in linux and x86_64.

3 Likes

Incredible.

Does it make sense to make this available via the automatic FFI – i.e. due to the slow down when crossing Prolog - library boundaries.

Edit:

I was always thinking that C is as close as bare-bone as it gets and the difference to working directly in assembly is negligible – apparently I was very wrong.

Dan

Dan

For many use cases it does make sense because you cross the prolog - library boundary only to populate the data, which many times comes from I/O of some kind which is orders of magnitudes slower than prolog. The speed up is so impressive that it may even pay off in other cases.

One could envision creating a non-portable a high-performance swi-prolog fork – something that will only work on Intel processor architecture.

I guess, the β€œmarket” is large enough to make this worthwhile …

Although having an ARM port of the flat assembler would be great as well β€”

1 Like

Just to show the speed of this from prolog and the new version of the ffi pack from @Jan:


6 ?- try(100_000_000).
Correct to: "plunit_array_basic:try(100000000)"? yes
array(<C long[100000000]>(0x555dbace4000))
array(<C long[100000000]>(0x555dea7d6000))
% 2 inferences, 0.139 CPU in 0.140 seconds (99% CPU, 14 Lips)
true.

That is 140 milliseconds to subtract two arrays with 100 million elements. That is very very fast.

1 Like

What does subtract array mean

Also, could you show how exactly you used FFI to interface … would be great to see, so i can try this out as well

1 Like

Here is some sample code:

% Use ffi package for dynamic communication with C
:- use_module(library(ffi)).


% Add linasm to file search path,
% ./linasm/include/Array.h and ./linasm/liblinasm.so need to
% exist in the directory where this prolog file is located.
:- prolog_load_context(directory,Dir1),
   assertz((
      user:file_search_path(linasm,Dir) :-
         absolute_file_name(Dir1/linasm,Dir)
      )).

% Hook to pass -I flag
ffi:cpp_hook(path(gcc), ['-E', '-xc', '-I',IncDir, -]) :-
   absolute_file_name(linasm(include),IncDir).

% Import sample function from headers
:- c_import("#include \"Array.h\"",                  % ffi:cpp_hook provides -I flag
            [ linasm(lib/'liblinasm.so') ],
	    [
	      'Array_SubVector_sint64'(  *int,       % sint64_t target[],
	                                 *int,       % const sint64_t source[],
				                      int,        % size_t size,
				         [void])
	    ]).

try(Count) :-
   array(1,Count,A1),
   array(2,Count,A2),
   time('Array_SubVector_sint64'(A1,A2,Count)),
   time(read_array(0, Count, A1, List)),
   format("Array1 - Array2 = ~w",[List]).

% Allocate a C array:
% Start, Start+1, Start+2, ...
array(Start,Count,Array) :-
   End is Count + Start - 1,
   time(
     (  numlist(Start,End,L),
        c_alloc(Array, long[]=L),
	    print(array(Array))
     )
   ).

% Read C array back into prolog List
read_array(I, Count, Data, [H|T]) :-
   I < Count,
   !,
   c_load(Data[I], H),
   I2 is I + 1,
   read_array(I2, Count, Data, T).
read_array(_, _, _, []).

Query:

2 ?- try(10).
array(<C long[10]>(0x5652d646e140))
% 60 inferences, 0.000 CPU in 0.000 seconds (94% CPU, 1144187 Lips)
array(<C long[10]>(0x5652d646ff90))
% 60 inferences, 0.000 CPU in 0.000 seconds (58% CPU, 972842 Lips)
% 2 inferences, 0.000 CPU in 0.000 seconds (96% CPU, 223964 Lips)
% 152 inferences, 0.000 CPU in 0.000 seconds (96% CPU, 4106665 Lips)
Array1 - Array2 = [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]
true.

Subtract array means the difference between two arrays, e.g. array1 - array2.

1 Like

I am really curious if I could β€œhack” a backtrackabale array or even hash with this – and whether its worthwhile performance wise.

1 Like