This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 15k traffic Daily!!!

Transparent execution of Fortran code from the Erlang machine using ports




Desk of Contents

  1. Transparent execution of Fortran code from the Erlang machine using ports
    1. The plan
    2. The Fortran program
    3. The Erlang program
    4. Conclusion

Joe Armstrong, creator of the Erlang programming language, stated a few occasions that, although the Erlang system is the proper software for writing applications designed for concurrent execution, it’s not one of the best software for compute-intensive duties, resembling numerical calculations. These duties, he stated, can be finest served by calling an exterior program written in Fortran.

The issue, nonetheless, is that he by no means instructed us how one can run such a program from contained in the Erlang machine.



The plan

We’re going to write a Fortran program that receives enter and does some calculations with the values offered by the person. As a result of our downside right here shouldn’t be how one can write Fortran, however reasonably how one can run this system from contained in the Erlang runtime, a easy program will just do wonderful. For this train, we are going to write a program that calculates the power in accordance with Newton’s 2nd legislation.

As a way to interface with the Fortran program, we use a genserver course of that manages an Erlang port. Ports are Erlang processes that permit operating exterior applications and work together with them in the identical approach we work together with processes within the Erlang machine, by sending and receiving messages.

Our goal is to name the genserver API in Erlang, have the perform transparently execute within the Fortran program (that’s, as if it had been referred to as domestically), and return the proper end result.

    Eshell V13.1.2  (abort with ^G)
    1> f90:start_link("./newton").
    {okay,<0.84.0>}
    2> f90:power(90,80).
    7200 
Enter fullscreen mode

Exit fullscreen mode



The Fortran program

First, we concentrate on the Fortran program that may successfully carry out the calculations. As we stated, we’re going to calculate the power utilizing newton’s system, which is, as everyone knows, outlined as: f = m * a.

Let’s begin with the only program potential:

    ! newton0.f90
    program newton
      implicit none
      integer mass, accel

      mass = 90
      accel = 80

      write (*,'(10i0)') power(mass, accel)

    incorporates
      perform power(m, a) end result (f)
        implicit none
        integer m, a, f

        f = m * a
      finish perform power
    finish program newton
Enter fullscreen mode

Exit fullscreen mode

This system consists of a easy perform definition for the Newtonian system, a few variable declarations and assignments, and a write assertion that prints the results of making use of the perform to the variables as arguments.

We compile this system with gfortran newton0.f90 -o newton. Operating it within the terminal produces the proper end result.

For the following step, we have to course of person enter:

    ! newton.f90
    program newton

      implicit none
      integer rstat
      integer mass, accel
      character(20) :: enter

      do whereas(.true.)
         do whereas(.true.)
        learn(*,'(A)',iostat=rstat) enter

        if (rstat /= 0) then
           cease
        else
           if (enter(1:4) == 'mass') then
              name maybe_read_int(mass, 4 + 2) 
           else if (enter(1:5) == 'accel') then
              name maybe_read_int(accel, 5 + 2)
           else if (enter(1:6) == 'return') then
              exit
           else
              write(*,*) 'unhealthy enter' 
           finish if
        finish if
         finish do

         write (*,'(10i0)') power(mass, accel)

         mass = 0
         accel = 0
      finish do

    incorporates
      subroutine maybe_read_int(discipline, index)
        implicit none
        integer discipline, index

        learn(enter(index:), *, iostat=rstat) discipline
        if (rstat == 0) then
           write(*,'(10i0)') discipline
        else
           write(*,*) 'unhealthy enter'
        endif
      finish subroutine maybe_read_int

      perform power(m, a) end result (f)
        implicit none
        integer m, a, f

        f = m * a
      finish perform power
    finish program newton
Enter fullscreen mode

Exit fullscreen mode

This system begins with a loop, which reads the usual enter, and assigns its worth to a string. The enter is matched to the anticipated patterns:

  • mass [value]: shops the worth within the mass variable
  • accel [value]: shops the worth within the accel variable
  • return: exits the loop and proceeds to the following step

Subsequent, this system prints the results of the power perform over the variables, similar to within the earlier snippet. Let’s compile this system and run it within the terminal to see it in motion.

    > ./newton
    > mass 90
    90
    > accel 80
    80
    > return
    7200
Enter fullscreen mode

Exit fullscreen mode

Nice, we have now efficiently written a Fortran program that calculates the power utilizing the Newtonian system. Now, we have to write an Erlang program that is ready to run it.



The Erlang program

As we stated, we wish to have the ability to name an Erlang perform that produces the end result from the Fortran program’s execution. The suitable approach to do that in Erlang is utilizing ports. Acording to the documentation:

Ports present the essential mechanism for communication with the exterior world, from Erlang’s standpoint. The ports present a byte-oriented interface to an exterior program. When a port is created, Erlang can talk with it by sending and receiving lists of bytes (not Erlang phrases). Which means that the programmer might need to invent an appropriate encoding and decoding scheme.

When to make use of: Ports can be utilized for all types of interoperability conditions the place the Erlang program and the opposite program runs on the identical machine. Programming is pretty straight-forward.

Most issues within the Erlang system are processes, and ports are not any exception. A port is a processes that sends and receives messages from different processes within the Erlang runtime, and sends and receives messages from the exterior program.

One key distinction of message passing from ports to the exterior program, in contrast with message passing between processes contained in the Erlang runtime, is that inner processes perceive Erlang phrases (e.g. atoms, tuples, information, maps), whereas the exterior program completely doesn’t. Every part we will do is ship and obtain binaries.

That is similar to what occurs within the distributed structure of microservices applied in several programming languages. For instance, three providers operating Node, JVM, and Python can not share objects native to their respective languages. They have to as an alternative resort to a standard binary (string) protocol (e.g. JSON) for the API, and implement encoding/decoding internally.

Fortunately for us, our Fortran program is designed to anticipate quite simple binary patterns. Let’s have a look at how we create a port and ship and obtain messages.

    Eshell V13.1.2  (abort with ^G)
    1> Port = open_port({spawn, "./newton"}, [use_stdio, exit_status]). 
    #Port<0.5>
    2> Port ! {self(), {command, "mass 90n"}}.
    {<0.82.0>,{command,"mass 90n"}}
    3> flush().
    Shell bought {#Port<0.5>,{knowledge,"90n"}}
    okay
    4> Port ! {self(), {command, "accel 90n"}}.
    {<0.82.0>,{command,"accel 90n"}}
    5> flush().
    Shell bought {#Port<0.5>,{knowledge,"90n"}}
    okay
    6> Port ! {self(), {command, "returnn"}}.  
    {<0.82.0>,{command,"returnn"}}
    6> flush().
    Shell bought {#Port<0.5>,{knowledge,"8100n"}}
    okay
Enter fullscreen mode

Exit fullscreen mode

We create a port with the Erlang library perform open_port/2, which receives the command to the exterior program and a few choices, and returns the port Pid. We use the Pid to ship messages to the port, which it is going to relay to the exterior program utilizing the stdin.

Right here, we’re making a port to the Fortran program “./newton”, and sending it three messages. The flush() name reads the messages acquired by the Erlang shell course of. Discover the third message: it’s the results of the power() perform, executed by the Fortran program!

We’re very near wrapping this up. All that’s left is to place this performance in a genserver that manages the port and gives a transparent interface in accordance with the OTP requirements.

    %% f90.erl
    -module(f90).
    -behaviour(gen_server).

    -export([start_link/1, force/2, stop/0]).
    -export([init/1, handle_call/3, handle_cast/2]).

    %% API
    start_link(Filename) ->
        gen_server:start_link({native, ?MODULE}, ?MODULE, Filename, []).

    cease() ->
        gen_server:solid(?MODULE, cease).

    power(Mass, Accel) ->
        gen_server:name(?MODULE, {power, Mass, Accel}).

    %% callbacks
    init(Filename) ->
        process_flag(trap_exit, true),
        Port = open_port({spawn, Filename}, [use_stdio, exit_status]),
        {okay, {port, Port}}.

    handle_call({power, Mass, Accel}, _From, {port, Port} = State) ->
        call_port(mass(Mass), Port),
        call_port(accel(Accel), Port),
        Res = call_port(end result(), Port),
        {reply, Res, State}.

    handle_cast(cease, {port, Port}) ->
        port_close(Port),
        {cease, regular, []}.

    call_port(X, Port) ->
        port_command(Port, X),
        obtain
        {_, {knowledge, Knowledge}} ->
            TrimmedData = string:trim(Knowledge),
            list_to_integer(TrimmedData)
        after 500 -> nil
        finish.

    accel(X) -> "accel " ++ integer_to_list(X) ++ "n".
    mass(X) -> "mass " ++ integer_to_list(X) ++ "n".
    end result() -> "returnn".
Enter fullscreen mode

Exit fullscreen mode

We begin the genserver with start_link/1 by offering the exterior program command as argument. The init/1 perform runs as a callback, spawns the port, and shops the port Pid within the genserver state.

The power/2 perform takes two integers, mass and acceleration, and can callback a handler that sends messages to the port and receives the response from the exterior program.

With this, we have now applied precisely the performance we wished at first: a server that gives a easy Erlang perform and produces the results of a calculation accomplished in an exterior Fortran program.



Conclusion

The pc is an superior machine, and it gives so many alternative instruments and patterns with which we will create applications. It’s a waste of intelligence to be confined to a single programming language.

On this train, we confirmed that with a easy assemble, the Erlang port, we will interface with exterior applications in different languages. As soon as we arrange a standard binary protocol between the 2 applications, we will ship and obtain messages similar to we do contained in the Erlang machine, requesting execution and getting again outcomes.

The Article was Inspired from tech community site.
Contact us if this is inspired from your article and we will give you credit for it for serving the community.

This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 10k Tech related traffic daily !!!

Leave a Reply

Your email address will not be published. Required fields are marked *

Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?