The Computer Language
24.04 Benchmarks Game

spectral-norm Erlang #2 program

source code

% The Computer Language Benchmarks Game
% https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
%   contributed by Fredrik Svahn

-module(spectralnorm).
-export([main/1]).
-compile( [ inline, { inline_size, 1000 } ] ).

main([Arg]) ->
    register(server, self()),
    N = list_to_integer(Arg),
    {U, V} = power_method(N, 10, erlang:make_tuple(N, 1), []),
    io:format("~.9f\n", [ eigen(N, U, V, 0, 0) ]),
    erlang:halt(0).

% eigenvalue of V
eigen(0, _, _, VBV, VV) when VV /= 0 -> math:sqrt(VBV / VV);

eigen(I, U, V, VBV, VV) when I /= 0 ->
    VI = element(I, V),
    eigen(I-1, U, V, VBV + element(I, U)*VI, VV + VI*VI).

% 2I steps of the power method
power_method(_, 0, A, B) -> {A, B};
power_method(N, I, A, _B) ->
    V = atav(N, A),
    U = atav(N, V),
    power_method(N, I-1, U, V).


% return element i,j of infinite matrix A
a(II,JJ) -> 1/((II+JJ-2)*(II-1+JJ)/2+II).


% multiply vector v by matrix A
av(N, V) -> pmap(N, fun(Begin, End) -> av(N, Begin, End, V) end).

av(N, Begin, End, V) -> server ! { self(), [ avloop(N, I, V, 0.0) || I <- lists:seq(Begin, End) ]}.

avloop(0, _, _, X) ->  X;
avloop(J, I, V, X) ->  avloop(J-1, I, V, X + a(I, J)*element(J, V) ).


% multiply vector v by matrix A transposed
atv(N, V) -> pmap(N, fun(Begin, End)-> atv(N, Begin, End, V) end).

atv(N, Begin, End, V) -> server ! { self(), [ atvloop(N, I, V, 0.0) || I <- lists:seq(Begin, End) ]}.

atvloop(0, _, _, X) -> X;
atvloop(J, I, V, X) -> atvloop(J-1, I, V, X + a(J, I)*element(J, V) ).


% multiply vector v by matrix A and then by matrix A transposed
atav(N, V) -> atv(N, av(N, V)).


%Helper function for multicore
pmap(N, F) ->
    Chunks = chunks(0, erlang:system_info(logical_processors), N, []),
    Pids = [spawn(fun()-> F(Begin, End) end) || {Begin, End} <- Chunks],
    Res = [ receive {Pid, X} -> X end || Pid <- Pids],
    list_to_tuple(lists:flatten(Res)).

chunks(I, P, N, A) when I == P-1 -> lists:reverse([{I*(N div P)+1, N} | A ]);
chunks(I, P, N, A) -> chunks(I+1, P, N, [{ I*(N div P)+1, (I+1)*(N div P)} | A ]).

    

notes, command-line, and program output

NOTES:
64-bit Ubuntu quad core
Erlang/OTP 26 [erts-14.2.2]
[source] [64-bit] [smp:4:4]
[ds:4:4:10] [async-threads:1] [jit:ns]



 Mon, 04 Mar 2024 05:56:17 GMT

MAKE:
mv spectralnorm.erlang-2.erlang spectralnorm.erl
/opt/src/otp_src_26.2.2/bin/erlc spectralnorm.erl

1.62s to complete and log all make actions

COMMAND LINE:
 /opt/src/otp_src_26.2.2/bin/erl -smp enable -noshell -run  spectralnorm main 5500

PROGRAM OUTPUT:
1.274224153