Till KTH:s startsida Till KTH:s startsida

Next step

A client and server solution

This is what you need to be a client in the distributed computation:

The server is not much more complicated:

Improving the calculation

We can of course do the depth calculation more efficient. The first attempt would be to be smarter and avoid constructing tuples on the heap for every complex number in the recursion. If you explore this option you might end up with a test/3 function that looks as follows (the real and imaginary parts have been broken out):

test(M, _Zr, _Zi, _Cr, _Ci, M) ->
    0;
test(I, Zr, Zi, Cr, Ci, M) ->
    Zr2 = Zr*Zr,
    Zi2 = Zi*Zi,
    A2 = Zr2 + Zi2,
    if
    A2 < 4.0 ->
        Sr = Zr2 - Zi2 + Cr,
        Si = 2*Zr*Zi + Ci,
        test(I+1, Sr, Si, Cr, Ci, M);
    true ->
        I
    end.

Running a benchmark on my laptop this will cut the execution time in half.

Native code to do the calculation

The next step is to implement this in C and then load it as a foreign function (NIF). This will require some C skills but you will quickly get something up and running since this is a very simple function that only handles floating point arithmetic. Here is an example of a C file and Erlang file that will do the trick.

The C file needs to be compiled as a shared library and is then included in the Erlang virtual machine --  doing this is not recommended, if the C function crashes the whole Erlang machine crashes . If you want to give it a try you compile like this:

 unix> gcc -o depth.so -I/usr/lib/erlang/usr/include -fpic -shared depth.c
windows> cl -LD -MD -Fe depth.dll depth.c

This will cut the execution time down another factor five so we are now a factor 10 from our original code.

If we now parallelize the code we gain  another factor 3 (on my 4 core Intel machine) so we are now 30 times faster than the original code.

.

OSX

Marcel Eschmann tried the NIF interface on OSX and here are his findings using the C complex library.

To compile the depth.c code:

> gcc -std=c99 -fPIC -shared -o depth.so depth.c -I /usr/local/lib/erlang/erts-8.2/include/ -flat_namespace -undefined suppress;

Of course the –std=c99 is optional and is only required for the <complex.h> import. On OSX, the normal Unix compile command will tell you that the enif_* functions are not supported for your architecture, so you have to:

  • Add the absolute path to the erlang "erl_nif.h"
  • Add “-flat_namespace -undefined suppress”

The image he generated:

Fjord

Lärare Johan Montelius skapade sidan 20 februari 2015

Johan Montelius redigerade 20 februari 2015

* mandel.pdf
En klient och server:


* server.erl
* client.erl
* print.erl
 

Lärare Johan Montelius ändrade rättigheterna 25 november 2015

Kan därmed läsas av lärare och ändras av lärare.

Lärare Johan Montelius ändrade rättigheterna 26 februari 2016

Kan därmed läsas av alla och ändras av lärare.

Lärare Johan Montelius ändrade rättigheterna 17 januari 2017

Kan därmed läsas av lärare och ändras av lärare.

Lärare Johan Montelius ändrade rättigheterna 17 februari 2017

Kan därmed läsas av alla och ändras av lärare.
Johan Montelius redigerade 18 februari 2017

* mandel.pdf
A client and server:


* server.erl
* client.erl
* print.erl
* color.erl
* brot.erl
* cmplx.erl
 

We can of course do the depth calculation more efficient. The first attempt would be to be smarter and avoid constructing tuples on the heap for every complex number in the recursion. If you explore this option you might end up with a test/3 function that looks as follows (the real and imaginary parts have been broken out):¶

test(M, _Zr, _Zi, _Cr, _Ci, M) ->    0;test(I, Zr, Zi, Cr, Ci, M) ->    Zr2 = Zr*Zr,    Zi2 = Zi*Zi,    A2 = Zr2 + Zi2,    if     A2 < 4.0 ->        Sr = Zr2 - Zi2 + Cr,        Si = 2*Zr*Zi + Ci,        test(I+1, Sr, Si, Cr, Ci, M);    true ->        I    end. Running a benchmark on my laptop this will cut the execution time in half. ¶

The next step is to implement this in C and then load it as a foreign function (NIF). This will require some C skills but you will quickly get something up and running since this is a very simple function that only handles floating point arithmetic. Here is an example of a C file and Erlang file that will do the trick.¶


* depth.erl
* depth.c
The C file needs to be compiled as a shared library and is then included in the Erlang virtual machine --  doing this is not recommended, if the C function crashes the whole Erlang machine crashes . If you want to give it a try you compile like this:¶

unix> gcc -o depth.so -fpic -shared depth.c windows> cl -LD -MD -Fe depth.dll depth.c This will cut the execution time down another factor five so we are now a factor 10 from our original code. ¶

If we now parallelise the code we gain  another factor 3 (on my 4 core Intel machine) so we are now 30 times faster than the original code.¶

Johan Montelius redigerade 18 februari 2017

* mandel.pdf
A client and server:


* server.erl
* client.erl
* print.erl
* color.erl
* brot.erl
* cmplx.erl
 

We can of course do the depth calculation more efficient. The first attempt would be to be smarter and avoid constructing tuples on the heap for every complex number in the recursion. If you explore this option you might end up with a test/3 function that looks as follows (the real and imaginary parts have been broken out):

test(M, _Zr, _Zi, _Cr, _Ci, M) ->    0;test(I, Zr, Zi, Cr, Ci, M) ->    Zr2 = Zr*Zr,    Zi2 = Zi*Zi,    A2 = Zr2 + Zi2,    if     A2 < 4.0 ->        Sr = Zr2 - Zi2 + Cr,        Si = 2*Zr*Zi + Ci,        test(I+1, Sr, Si, Cr, Ci, M);    true ->        I    end. Running a benchmark on my laptop this will cut the execution time in half.

The next step is to implement this in C and then load it as a foreign function (NIF). This will require some C skills but you will quickly get something up and running since this is a very simple function that only handles floating point arithmetic. Here is an example of a C file and Erlang file that will do the trick.


* depth.erl
* depth.c
The C file needs to be compiled as a shared library and is then included in the Erlang virtual machine --  doing this is not recommended, if the C function crashes the whole Erlang machine crashes . If you want to give it a try you compile like this:

unix> gcc -o depth.so -fpic -shared depth.c windows> cl -LD -MD -Fe depth.dll depth.c This will cut the execution time down another factor five so we are now a factor 10 from our original code.

If we now parallelise the code we gain  another factor 3 (on my 4 core Intel machine) so we are now 30 times faster than the original code.

Hmm, there might be something wrong with my C code, colours are a bit strange. Hmm, strange things going on.¶

OSX Marcel Eschmann tried the NIF interface on OSX and here are his findings using the C complex library.¶

To compile the depth.c code:¶

> gcc -std=c99 -fPIC -shared -o depth.so depth.c -I /usr/local/lib/erlang/erts-8.2/include/ -flat_namespace -undefined suppress; Of course the –std=c99 is optional and is only required for the <complex.h> import. On OSX, the normal Unix compile command will tell you that the enif_* functions are not supported for your architecture, so you have to:¶


* Add the absolute path to the erlang "erl_nif.h"
* Add “-flat_namespace -undefined suppress”
The image he generated:¶

Fjord