spawn_link chaining other processes? - erlang

If process A spawn_link()'s process B and then process B spawn()'s process C, is the only way for process A to catch an error in process C if we replace "spawn()" for "spawn_link()" in process B?
I believe if this isn't replaced, process A will only know if process B dies?

When process B spawns process C, it basically forgets about it; in this case, if C is dying, process B will have no idea about it. If process B spawns process C using spawn_link, process C will be linked to B as child (C) - parent (B): if C dies, B will be notified and depending on the implementation, it can die (A will be notified) or survive further.

Related

Processes with unidirectional links

I need to create processes with unidirectional links. Say I have three linked processes
grandparent <- parent <- child
The processes do their job and die, but are blocked by the processes generated by them.
When the child dies, the parent and grandparent also die, but not the other way around.
The toy example would be processed that just create children and wait for them to die:
(init)
(wait) <- (init)
(wait) <- (wait) <- (init)
(wait) <- (wait) <- (die)
(wait) <- (die)
(die)
For the example not to be infinitely recursive, let's say that each process has only one job: on (init) it tosses a coin, on heads it spawns a child process, or on tails, it dies.
What is the nice way of doing this in Erlang/OTP?
Each parent should monitor its immediate children (for example, using spawn_monitor.
When a monitored process dies, the VM sends a {'DOWN', MonitorRef, process, Pid, Info} message to the monitoring process, then the monitoring process can just exit or throw an error.
E.g:
{Pid, MonitorRef} = spawn_monitor(?MODULE, child, []),
receive {'DOWN', MonitorRef, process, Pid, Info} -> exit(Info) end.

Rules to convert a CFG to a NDPA?

I have to define an FA by using this grammar:
S -> aSb
S -> c
S -> dA
A -> Sd
How do I manage the first rule and the last one?
For the second one I think I have to create another state (the final one) and link S and this new state. For the third one instead, I think I have to create the state "A" and link it to S by passing "d".
There are algorithms you can use to get a PDA from a CFG: look into top-down and bottom-up parsers, for instance. What I think of as the usual proof that PDAs accept languages generated by CFGs, and vice versa, uses such a construction.
An alternative is to understand the language generated by the grammar, and to design a PDA for it directly. This is less mechanical but has the potential to yield a more concise PDA. If you want to go this route, we can first simplify the grammar by recognizing the nonterminal A can safely be replaced by the RHS of the only production for it:
S -> aSb
S -> c
S -> dSd // removed A -> Sd and replaced here
How does this grammar work?
You have c in the middle by the 2nd production;
You have matching ds on the left and right of the c;
You have as on the left matching bs on the right of c.
A PDA should work as follows:
Read as and ds until you see a c. Push everything on the stack as you go. When you see a c, go to the next state, but don't push the c.
Read bs and ds, popping as and ds from the stack, until:
The topmost stack symbol doesn't match input; crash.
You run out of input with symbols still on the stack; crash.
You run out of stack symbols with input remaining; crash.
You run out of stack and input simultaneously; accept.
Here's a transition table:
q s x q' s'
------------------------------
q0 a,d,Z a q0 aa,ad,aZ
q0 a,d,Z d q0 da,dd,dZ
q0 a,d,Z c q1 a,d,Z
q1 a b q1 -
q1 d d q1 -
If we accept in q1 by empty stack, these transitions are enough. If we want to accept by empty stack or accepting state, we could add a transition like f(q1, Z, -) = (q2, Z) and make q2 accepting; the PDA would transition there nondeterministically and would crash unless the input were also exhausted.

How can I fetch each part from An Erlang Pid?

pid(A, B, C) can generate a pid <A.B.C>, how can I get A, B and C from a pid?
You can use pid_to_list, Erlang doc, but you probably shouldn't since it is generally a bad practice.

How does Erlang schedule work for multicore CPU machines?

I am learning Erlang and am quite impressed how easy it is to parallelize work. To practice a bit I dug up the good old Fibanocci sequence. In the following code I try to take advantage of parallelization by computing the expensive products three at a time.
-module (fib4).
-export ( [main/1] ).
main (N) ->
fib (list_to_integer (atom_to_list (hd (N) ) ) ),
halt (0).
path (1, Acc) -> Acc;
path (N, Acc) when N rem 2 =:= 0 ->
path (N - 1, [step | Acc] );
path (N, Acc) ->
path ( (N - 1) div 2, [jump | Acc] ).
fib (N) -> fib (1, 1, path (N, [] ) ).
fib (N, Nplus1, [Last] ) ->
case Last of
step -> Nplus1;
jump -> N * N + Nplus1 * Nplus1
end;
fib (N, Nplus1, [jump | T] ) ->
Pid = self (),
spawn (fun () -> Pid ! {n1sq, Nplus1 * Nplus1} end),
spawn (fun () -> Pid ! {mul, 2 * N * Nplus1} end),
spawn (fun () -> Pid ! {nsq, N * N} end),
{Nsq, N1sq, Mul} = loop (0, 0, 0),
fib (Nsq + N1sq, N1sq + Mul, T);
fib (N, Nplus1, [step | T] ) ->
fib (Nplus1, N + Nplus1, T).
loop (Nsq, N1sq, Mul) ->
receive
{nsq, Val} ->
if
N1sq > 0 andalso Mul > 0 -> {Val, N1sq, Mul};
true -> loop (Val, N1sq, Mul)
end;
{n1sq, Val} ->
if
Mul > 0 andalso Nsq > 0 -> {Nsq, Val, Mul};
true -> loop (Nsq, Val, Mul)
end;
{mul, Val} ->
if
N1sq > 0 andalso Nsq > 0 -> {Nsq, N1sq, Val};
true -> loop (Nsq, N1sq, Val)
end
end.
I am running this code on a Phenom X4 and during the minute it takes on my machine to calculate fib(10000000) only one to two cores are working and the others are idling around.
My questions are:
Who decides onto how many cores the worker threads are distributed? The Erlang node or my OS (ubuntu with 2.6.38 in my case)?
Do I lose speed due to the fact that two or three cores are idling?
Erlang's default behavior has historically been to run one scheduler, which is basically a native OS thread, which chooses Erlang tasks to run from a queue. With the advent of multi-core and multi-processor systems, the runtime was extended to take advantage. Starting the runtime with -smp enabled will cause the runtime to create multiple schedulers, usually one per logical CPU. You can manually specify the number of schedulers with the -S flag e.g. -S 16.
This is documented in the Erlang Run-Time System Reference Manual.
A deeper discussion of SMP support can be found in this discussion thread.
EDIT
I should also point out that, as of R12B, SMP is enabled by default on platforms that support it (equivalent to the -smp auto flag). If you're curious about your own runtime, the following quote from the discussion thread will be of interest:
You can see what was chosen at the first line of printout from the
"erl" command. E.g.
Erlang (BEAM) emulator version 5.6.4 [source] [smp:4] [asynch-threads:0] .....
The "[smp:4]" above tells that the SMP VM is run and with 4 schedulers.
The reason you see so little parallelism is that your program is basically sequential. All the work is being done in one process in the fib/3 function. The processes you spawn all just send a message and then die and the spawning process synchronously waits for these messages so there is no real concurrency. You could just as well just call the loop/3 function directly with these values.
Otherwise it is as others have mentioned that Erlang automatically uses all the multiple cores available and distributes processes across these where possible. In your case however there is little need to do this and no gain so the system does not do it.
This is actually one of the more difficult things in writing concurrent applications. It is not enough to just spread things into many processes, you actually have to make sure that these processes actually run concurrently. It means rethinking your algorithms, which can be difficult.
Erlang does not use threads in the traditional sense. The Erlang VM creates one system thread for each hardware core of the CPU. When you start a thread in Erlang, you are really creating a "task", which is different from a system thread. Erlang manages these tasks inside of the VM.
Depending on VM and it's configuration, these tasks may or may not be mapped to individual CPU cores, which I believe is what you are seeing here.
There is an interesting blog article you might like here.

Testing intersection of two regular languages

I want to test whether two languages have a string in common. Both of these languages are from a subset of regular languages described below and I only need to know whether there exists a string in both languages, not produce an example string.
The language is specified by a glob-like string like
/foo/**/bar/*.baz
where ** matches 0 or more characters, and * matches zero or more characters that are not /, and all other characters are literal.
Any ideas?
thanks,
mike
EDIT:
I implemented something that seems to perform well, but have yet to try a correctness proof. You can see the source and unit tests
Build FAs A and B for both languages, and construct the "intersection FA" AnB. If AnB has at least one accepting state accessible from the start state, then there is a word that is in both languages.
Constructing AnB could be tricky, but I'm sure there are FA textbooks that cover it. The approach I would take is:
The states of AnB is the cartesian product of the states of A and B respectively. A state in AnB is written (a, b) where a is a state in A and b is a state in B.
A transition (a, b) ->r (c, d) (meaning, there is a transition from (a, b) to (c, d) on symbol r) exists iff a ->r c is a transition in A, and b ->r d is a transition in B.
(a, b) is a start state in AnB iff a and b are start states in A and B respectively.
(a, b) is an accepting state in AnB iff each is an accepting state in its respective FA.
This is all off the top of my head, and hence completely unproven!
I just did a quick search and this problem is decidable (aka can be done), but I don't know of any good algorithms to do it. One is solution is:
Convert both regular expressions to NFAs A and B
Create a NFA, C, that represents the intersection of A and B.
Now try every string from 0 to the number of states in C and see if C accepts it (since if the string is longer it must repeat states at one point).
I know this might be a little hard to follow but this is only way I know how.

Resources