What does a “successor” stand for in llvm? - llvm

When I reading the llvm document, especially the BasicBlock part, the concept “successor” appears a lot, so what is it?

Both terms, basic block and successor, are coming from the field of Control Flow Analysis (or CFA).
In CFA, a program is represented using Control Flow Graph (or CFG).
Each vertex (or node) in a CFG is a basic block. Since CFG is a directed graph, a basic block may have incoming and outcoming edges. E.g.: A -> B -> C. Incoming edges are coming from predecessors, and the outcoming edges are leading to successors.
The set of successors/predecessors for the mentioned example (A -> B -> C):
pred(A) = {}
succ(A) = {B}
pred(B) = {A}
succ(B) = {C}
pred(C) = {B}
succ(C) = {}

A successor is the target of a the branch that ends a basic block.
For example, if a basic block ends with a five-way switch, then that block has six successors (five explicit and the switch's default). A basic block that ends with a return has no successors.

Related

Erlang - How is the creation integer (a part of a distributed pid representation ) actually created?

In a distributed Erlang system pids can have two different representations: i) internal; ii) external.
The internal representation has the following shape: < A.B.C >
The external representation, used for instance when a message has to travel across different nodes, is instead composed of the following elements: < node_id, ID, serial, creation > according to the official documentation.
Where node_id is the name of the node, ID and serial identify the process on node_id and creation is an integer used to distinguish the node from past (crashed) version of itself.
What I could not find is how the creation integer is created by the VM.
By setting a small experiment on my PC, I have seen that if I create and kill the same node several times the counter is always increased by 1, and by creating the same node on different machines, the creation integers are different, but have some similarities in their structure, for instance:
machine 1 -> creation integer = 1647595383
machine 2 -> creation integer = 1647596018
Do any of you have any knowledge about how this integer is created? If so could you please explain it to me and possibly reference some (more or less) official documentation?
The creation is sent as a part of the response to node registration in epmd, see details on that protocol.
If you have a custom erl_epmd module, you can also provide your own way of creating the creation-value.
The original creation is the local time of when the node with that name is first registered, and then it is bumped once for each time the name is re-registered.

Explicit throughput limiting on part of an akka stream

I have a flow in our system which reads some elements from SQS (using alpakka) and does some preporcessing (~ 10 stages, normally < 1 minute in total). Then, the prepared element is sent to the main processing (single stage, taking a few minutes). The whole thing runs on AWS/K8S and we’d like to scale out when the SQS queue grows above a certain threshold. The issue is, the SQS queue takes a long time to blow up, since there are a lot of elements “idling” in-process, having done their preprocessing but waiting for the main thing.
We can’t externalize the preprocessing stuff to a separate queue since their outcome can’t survive a de/serialization roundtrip. Also, this service and the “main” processor are deeply coupled (this service runs as main’s sidecar) and can’t be scaled independently.
The preprocessing stages are technically .mapAsyncUnordered, but the whole thing is already very slim (stream stages and SQS batches/buffers).
We tried lowering the interstage buffer (akka.stream.materializer.max-input-buffer-size), but that only gives some indirect benefit, no direct control (and is too internal to be mucking with, for my taste anyway).
I tried implementing a “gate” wrapper which would limit the amount of elements allowed inside some arbitrary Flow, looking something like:
class LimitingGate[T, U](originalFlow: Flow[T, U], maxInFlight: Int) {
private def in: InputGate[T] = ???
private def out: OutputGate[U] = ???
def gatedFlow: Flow[T, U, NotUsed] = Flow[T].via(in).via(originalFlow).via(out)
}
And using callbacks between the in/out gates for throttling.
The implementation partially works (stream termination is giving me a hard time), but it feels like the wrong way to go about achieving the actual goal.
Any ideas / comments / enlightening questions are appreciated
Thanks!
Try something along these lines (I'm only compiling it in my head):
def inflightLimit[A, B, M](n: Int, source: Source[T, M])(businessFlow: Flow[T, B, _])(implicit materializer: Materializer): Source[B, M] = {
require(n > 0) // alternatively, could just result in a Source.empty...
val actorSource = Source.actorRef[Unit](
completionMatcher = PartialFunction.empty,
failureMatcher = PartialFunction.empty,
bufferSize = 2 * n,
overflowStrategy = OverflowStrategy.dropHead // shouldn't matter, but if the buffer fills, the effective limit will be reduced
)
val (flowControl, unitSource) = actorSource.preMaterialize()
source.statefulMapConcat { () =>
var firstElem: Boolean = true
{ a =>
if (firstElem) {
(0 until n).foreach(_ => flowControl.tell(())) // prime the pump on stream materialization
firstElem = false
}
List(a)
}}
.zip(unitSource)
.map(_._1)
.via(businessFlow)
.wireTap { _ => flowControl.tell(()) } // wireTap is Akka Streams 2.6, but can be easily replaced by a map stage which sends () to flowControl and passes through the input
}
Basically:
actorSource will emit a Unit ((), i.e. meaningless) element for every () it receives
statefulMapConcat will cause n messages to be sent to the actorSource only when the stream first starts (thus allowing n elements from the source through)
zip will pass on a pair of the input from source and a () only when actorSource and source both have an element available
for every element which exits businessFlow, a message will be sent to the actorSource, which will allow another element from the source through
Some things to note:
this will not in any way limit buffering within source
businessFlow cannot drop elements: after n elements are dropped the stream will no longer process elements but won't fail; if dropping elements is required, you may be able to inline businessFlow and have the stages which drop elements send a message to flowControl when they drop an element; there are other things to address this which you can do as well

What if two blocks complete their POW at same time

Let's consider a scenario: suppose 2 miners pick up 2 different unconfirmed transactions and they complete the proof of work. If miner A adds the block first to blockChain then the block produced by miner B be will be wrong/useless because the last_Hash he used is now wrong and he has to use the last_hash of miner A that is added right a second before he was going to add his block.
e.g.
<b>current chian: block1--block2--block3</b>
<table>
<tr>
<td>Miner A </td>
<td>Miner B</td>
</tr>
<tr>
<td>LastHast=block3-hash<br>
currentHast=SHA(block3's_hash,timestemp,data,nonce) <br>
proof of work <br>
add---- Successfully add block4 <br>
</td>
<td>LastHast=block3-hash<br>
currentHast=SHA(block3's_hash,timestemp,data,nonce) <br>
proof of work <br>
add---- Fail because the last hash is now block4's not block3's So currentHash is wrong so the proof of work<br>
</td>
</tr>
</table>
**
**
Double spending is avoided by having other miners verify the proposed change on the ledger.
In your case two miners verified the transaction, published the result to the network and depending on your protocol this might be fine so the change on the ledger will take place.
Apart from that a timestamp server that ensures that you will always build on top of a unique chain of blocks.
The valid transactions are always on the longest chain, by longest, I mean the block number is bigger.
If minerA and minerB finished PoW at the same time, a fork is made
At the current time, both minerA and minerB transaction is stored on the fullnode, and the fullnode is waiting for the next block to be produced.
During the next block time, minerA finished PoW first, then the fork (data chain) on minerA is considered longer, thus minerA become the longest chain and considered valid, block on minerB is considered non-valid, and discared.
First of all, this is happening all the time, and the protocol is built to deal with it.
Let’s assume 2 miners, A and B, that find the PoW for a different set of transactions at the same time.
The next thing this miners will do is to broadcast their newly found blocks over the network.
This broadcast is not instantaneous (light speed is not instantaneous) and so miners near A will receive first the broadcast from A, and miners near B will receive first the broadcast from B.
At that instant, A neighbours will start working on a new block on top of the A block, while B neighbours will start working in a new block on top of the B block.
The networked has just forked, part of the network is working on a blockchain that ends on block A, other part is working on a blockchain that ends on block B.
Let’s assume now 2 new miners, C and D. C is a A neighbour and is working on a new block on top of the A block. D is a B neighbour and is working on a new block on top of the B block.
Imagine that C finds the PoW for a new block first than D. C will broadcast this block to the network. Eventually, D will receive this C block and will realize that the blockchain X -> A -> C has more PoW then the one its working on, X -> B.
By the protocol rules, D will discard immediately what it was working on, and will start to work on the PoW for a new block on top of X -> A -> C, thus resolving the network fork.

MPI_send and MPI_recv functions for multiple processors C++

I`m pretty new in MPI programming and got stuck in the middle of my project.
I want to write an MPI code for the following problem. I am not sure which functions from MPI is appropriate.
Here is the problem:
Processor 0 has a 2D vector or array of Edges={(0,4),(1,5)}. It needs to get some information from the other processors, which is not always a fixed processor, it depends on set Edges. Therefore, I need a for loop as follows:
if(my_rank==0)
{
for(all pairs (i,j) in Edges)
{
send i (or j) to Processor r (r depends on the index i)
recieve L_r from Processor r
create (L_i, L_j, min(L_i,L_j)) // want to broadcast to all later.
}
}
Now, I am not sure how to do it for processor r, should I do in a for loop?
Note that I can not do it in an if statement since I dont know which processor would be and so based on the number of processors I need an if statement which I don`t think is a right way. I might have so many processors which each holds some part of a matrix.
Need to point that I cannot communicate with a subgroup of communicators, since it all depends on the indices, basically, I want the labels for example indices (0,4) which need to communicate with P4 that holds it.
Any ideas are appreciated.
I would do it as follow:
1) Proc 0 construct a list of every processes it has to comunicate with.
2) Proc 0 broadcast this list to all processes (or only to the one he have to communicate with, but that will be more complicated, can be done once you got a version which works)
3) You perform your comm:
If(rank==0){...}
else if (rank in the list){...}

How to convert a graph that is NOT DAG to a graph that is DAG?

Hello there everyone,
Is there any general algorithms that takes a non DAG(directed acyclic graph) as input and outputs a directed acyclic graph.
Currently, I am not sure which data structures I will be using to represent my graph. But, I am searching just for the algorithm at this point.
Hope you guys can inform me on the matter.
Cheers~
I want to go from this:
To this:
NEW GRAPH GRAPH THIS IS ONLY FOR THE SOLUTION BeyelerStudios provided
You can always simply flip some edges to get an acyclic graph from a cyclic one (graph G with vertices V and edges E):
input: G(V,E), n = |V|
visited <- empty set
queue <- empty queue
for each node in V
// skip visited nodes
if visited.find(node)
continue
// push a dummy edge (node is unvisited)
queue.push(edge(inf, node))
while !queue.empty()
edge <- queue.pop()
if visited.find(edge.stop)
// potential cycle detected
if edge.start != edge.stop
// eliminate loops, if any
E.flip(edge)
else
visited.insert(edge.stop)
for each outgoing edge e at edge.stop
queue.push(e)
Depending on the queue you use you get different behaviour:
a stack (LIFO queue) results in depth-first traversal
a FIFO queue results in breadth-first traversal
a priority queue results in a DAG containing its spanning tree(s)
There's a caviat in the above code: potential cycle detected. Imagine a graph with vertices A, B, C and edges A->B, A->C, C->B. The above snippet detects a potential cycle when processing C->B last. If you want to disambiguate valid edges from edges introducing cycles at that point you need to show that there are no paths from B to C yet. This is a much harder task and there are some good answers (and hints) in this answer here: basically you'd need to perform another graph traversal to detect (or exclude) such a conflicting path.