How to merge variables from parallel flows in Activiti? - alfresco

Currently I have a sub-process which uses fork/join mechanism to create parallel flows. Lest assume that there are two flows: A, B. Each of that flows takes as input variables complex object CONTEXT. Also each of that flows make some calculation and updates CONTEXT inside. As a output each of flows return updated CONTEXT. The problem here is that in Join point, last result of CONTEXT overrides previous one. Lets assume that flow A fill be finished first with result CONTEXT_1 and flow B will return CONTEXT_2. So final result will be CONTEXT_2 and all changes from flow A will be lost.
The question here is - how to merge results from two flows?
UPDATE:
From my observations passed variable (CONTEXT) from SuperProcess to SubProcess are copied(CONTEXT') and after subProcess is finished, new value of passed variable(CONTEXT') will take place of original (CONTEXT).
In the example below I mean that all passed variables have the same name.
Example:
SuperProcess P1 (Variable: CONTEXT) calls SubProcess P2(variables are passed by copy);
SubProcess P2 (Variable: CONTEXT') creates two parallel flows(Tasks) A, B(variables are passed by copy);
A Task (Variable: CONTEXT_1) updates value of variable, finishes execution and returns variable;
3.1. CONTEXT_1 takes place of variable CONTEXT' so P2 can see only this new value as names of this variables the same;
Meanwhile B Task (Variable: CONTEXT_2) is still working and after some time updates variable, finishes execution and returns variable;
4.1. CONTEXT_2 takes place of variable CONTEXT_1 so P2 can see only this new value as names of this variables the same;
SubProcess P2 (Variable: CONTEXT_2) finish the execution and returns new veriable to SuperProcess.
Result -> CONTEXT_1 is lossed.
My aim scenario:
SuperProcess P1 (Variable: CONTEXT) calls SubProcess P2(variables are passed by copy);
SubProcess P2 (Variable: CONTEXT') creates two parallel flows(Tasks) A, B(variables are passed by copy);
A Task (Variable: CONTEXT_1) updates value of variable, finishes execution and returns variable;
3.1. CONTEXT_1 and CONTEXT are merged into CONTEXT_M1, in other words, only new changes of CONTEXT_1 will be applied to CONTEXT.
Meanwhile B Task (Variable: CONTEXT_2) is still working and after some time updates variable, finishes execution and returns variable;
4.1. CONTEXT_2 and CONTEXT_M1 are merged into CONTEXT_M2, in other words, only new changes of CONTEXT_2 will be applied to CONTEXT_M1 so previous update will be not lost;
SubProcess P2 (Variable: CONTEXT_M2) finish the execution and returns new veriable to SuperProcess.
Result -> CONTEXT_M2. All changes are saved.

After couple days of investigation we figured out that copying variables from SuperProcess to SubProcess is default behavior (link):
"You can pass process variables to the sub process and vice versa. The
data is copied into the subprocess when it is started and copied back
into the main process when it ends."
As the decision we pass variables into SubProcess under different name and merge with source variable after SubProcess finish:

When you say merge? What do you mean exactly?
What is your desired behavior at the emerge point?
If you want to maintain both contexts then use a map with the execution ID as the key, however, I doubt that is what you want.
Greg

Related

How to mock current time in elixir

I have some tests which depends on current time and am not able to find a solution for it so far. I have tried some mocking libraries like mock but it mocks the whole module and it fails.
Any help will be really appreciated(if I only mock DateTime.utc_now everything is ok)
Note: tests depends heavily on other DateTime and Date functions so mocking whole modules is not a very good option(I have tried this also but failed due to very complex cases and I need this in many tests)
Actual test:
I have two dates, start date and end date as input to a function which I am trying to test. Before calling the function for test purpose I insert some data relevent to the current week(current dat to next seven days). Now the function will get current datetime and check for specific days(each record will tell if it applies to current day of the week and for current time period range on which being iterated -> start and end dates).
e.g one record applies for mon -> 2:12 to 3:13
The solution which best suits my needs(simple, works well and according to the requirements described above) is:
define your own function/service MyDateTime.utc_now/0 and mock it in your tests. — Reference.
NB this answer is obsoleted since Elixir v1.8 Now the default parameters are not evaluated at compile time. Credits #HentikN.
Now the function will get current datetime and check for specific days [...]
This is where the real issue sits. You made your function not pure for no reason. Usually the purity means the function has no side effects, but blindly changing the outcome depending on the outside world does not sound as a robust approach either.
That said, you should make this function to accept a parameter now or like (it might be defaulted to now for the sake of brevity):
- def my_func(param) do
+ def my_func(param, dt \\ nil) do
+ dt = if is_nil(dt), do: DateTime.utc_now(), else: dt
(Naïve dt \\ DateTime.utc_now() won’t work because function heads are evaluated at the compile time.)
Now in your tests you might call this function passing the time you want and (which is even more important) your function is not a blackbox depending on the unrelated conditions from the outside anymore.

In metal does one vertex shader complete before the next vertex shader executes?

Suppose a Metal vertex shader A updates a buffer buf. Also suppose I have a second vertex shader B that is encoded after A. Can B use the results in buf or is it possible that B will begin executing before A has finished, meaning the contents of the buffer are not ready?
The second vertex shader B is free to execute before vertex shader A if they encoded in the same MTLRenderCommandEncoder. If you'd like to read the output of A in B, then they must be encoded by separate MTLRenderCommandEncoder's.
Note, however, the same is not true of compute dispatches within a MTLComputeCommandEncoder. The relevant part of the doc states:
Executing a Compute Command
To encode a command to execute a compute
function, call the dispatchThreadgroups:threadsPerThreadgroup: method
of MTLComputeCommandEncoder and specify the threadgroup dimensions and
the number of threadgroups. You can query the threadExecutionWidth and
maxTotalThreadsPerThreadgroup properties of MTLComputePipelineState to
optimize the execution of the compute function on this device.
For most efficient execution of the compute function, set the total number
of threads specified by the threadsPerThreadgroup argument to the
dispatchThreadgroups:threadsPerThreadgroup: method to a multiple of
threadExecutionWidth. The total number of threads in a threadgroup is
the product of the components of threadsPerThreadgroup:
threadsPerThreadgroup.width * threadsPerThreadgroup.height *
threadsPerThreadgroup.depth. The maxTotalThreadsPerThreadgroup
property specifies the maximum number of threads that can be in a
single threadgroup to execute this compute function on the device.
Compute commands are executed in the order in which they are encoded
into the command buffer. A compute command finishes execution when all
threadgroups associated with the command finish execution and all
results are written to memory. Because of this sequencing, the results
of a compute command are available to any commands encoded after it in
the command buffer.
To end encoding commands for a compute command encoder, call the endEncoding method of MTLComputeCommandEncoder.
After ending the previous command encoder, you can create a new
command encoder of any type to encode additional commands into the
command buffer.

Tensorflow Graphs : Are Tensorflow graphs DAG? What happens in assignAdd operations in tensor Variables

How is this graph acyclic? assign add op adds x to itself.
import tensorflow as tf
sess = tf.Session()
x = tf.Variable(1300,name="x")
y = tf.Variable(200, name="y")
z = tf.add(x, y,name="z")
b = x.assign_add(z)
init = tf.initialize_all_variables()
writer = tf.train.SummaryWriter("/tmp/logdir", sess.graph)
sess.run(init)
print(sess.run(b))
Clearly there is a bi-directional edge between AssignAdd and X.
Why is X depicted twice as a variable?
As Olivier points out, the graph for your program is a DAG. The graph visualizer takes some liberties when rendering the graph to make it easier to understand. In particular, there are no "bidirectional" edges in the runtime itself, but instead TensorFlow includes "reference edges" for variables, which are like passing a mutable value (like a pointer or a mutable reference) into a C/C++ function, as they allow the recipient to modify the same underlying storage used for the variable.
Note that it is legal for TensorFlow graphs to contain one or more cycles, or even nested cycles. The tf.while_loop() function provides a means of creating structured cycles to represent iterative computations, for which TensorFlow can compute gradients. However, for your use with a simple variable, you do not need a cycle.
Clearly there is a bi-directional edge between AssignAdd and X.
Each operation Assign or AssignAdd has two inputs and no output:
a tf.Variable: the variable to which we assign a value. Here you can see a bidirectional edge because the operation reads the old value from x and then writes back the new value
a tf.Tensor: the value assigned to the variable (or added to the variable)
Why is X depicted twice as a variable?
The variable x appears once in the graph in the big block named X, but is used twice:
in the operation tf.add(x, y): the graph reads the value of x as an input
in the AssignAdd operation: as said before, x is the tf.Variable input of the operation AssignAdd.
Conclusion
The graph is made acyclic because each operation wanting to update the value of x has the variable x as input, but not output. If the operation Assign had a variable as output, it would indeed lead to cycles.

Using Fortran90 and MPI, new to both, trying to use MPI_Gather to collect from a loop 3 different variables in each process

I am new to both Fortran90 and MPI. I have a loop that iterates different based on each individual process. Inside of that, I have a nested loop, and it is here that I make the computations that I desire along with the elements of the respective loops. However, I want to send all of this data, the x, the y, and the computed values using x and y, to my root process, 0. From here, I want to write all of the data to the same file in the format of 'x y computation'.
program fortranMPI
use mpi
!GLOBAL VARIABLE DECLARATION
real :: step = 0.5, x, y, comput
integer :: count = 0, finalCount = 5, outFile = 20, i
!MPI
integer :: ierr, myrank, mysize, status(MPI_STATUS_SIZE)
call MPI_INIT(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD,myrank,ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD,mysize,ierr)
if(myrank == 0) then
!I want to gather my data here?
end if
do i = 1, mysize, 1
if(myrank == i) then
x = -2. + (myrank - 1.)*step
do while (x<= 2.)
y= -2.
do while (y<=2.)
!Here is where I am trying to send my data!
y = y + step
end do
x = x + (mysize-1)*(step)
end do
end if
end do
call MPI_FINALIZE(ierr)
end program fortranMPI
I keep getting stuck trying to pass the data! If someone could help me out, that would be great! Sorry if this is simpler than I am making it, I am still trying to figure Fortran/MPI out. Thanks in advance!
First of all the program seems to not have any sense on what its doing. If you can be more specific on what you want to do, i can help further.
Now, usually, before the calculations, this if (myrank==0) statement, is where you send your data on the rest of the processes. Since process 0 will be sending data, you have to add code right after that in order for the processes to receive the data. Also you may need to add an MPI_BARRIER (call MPI_BARRIER), right before the start of the calculations, just to make sure the data has reached every process.
As for the calculation part, you also have to decide, not only where you send data, but also where the data is received and if you also need any synchronization on the communication. This has to do with the design of your program so you are the one who knows what exactly you want to do.
The most common commands for sending and receiving data are MPI_SEND and MPI_RECV.
Those are blocking commands, which means that the communication should be synchronized. One Send command should be matched with one Receive command before both processes can continue.
There are also non blocking commands, you can find them all here:
http://www.mpich.org/static/docs/v3.1/www3/
As for the MPI_GATHER command, this is used in order to gather data from a group of processes. This will only help you when you are going to use more than 2 processes to further accelerate your program. Except from that MPI_GATHER is used when you want to gather data and store them in an array fashion, and of course it's worth using only when you are going to receive lots of data which is definitely not your case here.
Finally about printing out results, i'm not sure if what you are asking is possible. Trying to open the same file handle using 2 processes, is probably going to lead to OS errors. Usually for printing out the results, you have rank 0 to do that, right after every other process has finished.

Error in MPI broadcast

Sorry for the long post. I did read some other MPI broadcast related errors but I couldn't
find out why my program is failing.
I am new to MPI and I am facing this problem. First I will explain what I am trying to do:
My declarations :
ROWTAG 400
COLUMNTAG 800
Create a 2 X 2 Cartesian topology.
Rank 0 has the whole matrix. It wants to dissipate parts of matrix to all the processes in the 2 X 2 Cartesian topology. For now, instead
of matrix I am just dealing with integers. So for process P(i,j) in 2 X 2 Cartesian topology, (i - row , j - column), I want it to receive
(ROWTAG + i ) in one message and (COLUMNTAG + j) in another message.
My strategy to do so is:
Processes: P(0,0) , P(0,1), P(1,0), P(1,1)
P(0,0) has all the initial data.
P(0,0) sends (ROWTAG+1) (in this case 401) to P(1,0) - In essense P(1,0) is responsible for dissipating information related to row 1 for all the processes in Row 1 - I just used a blocking send
P(0,0) sends (COLUMNTAG+1) (in this case 801) to P(0,1) - In essense P(0,1) is responsible for dissipating information related to column 1 for all the processes in Column 1 - Used a blocking send
For each process, I made a row_group containing all the processes in that row and out of this created a row_comm (communicator object)
For each process, I made a col_group containing all the processes in that column and out of this created a col_comm (communicator object)
At this point, P(0,0) has given information related to row 'i' to Process P(i,0) and P(0,0) has given information related to column 'j' to
P(0,j). I call P(i,0) and P(0,j) as row_head and col_head respectively.
For Process P(i,j) , P(i,0) gives information related to row i, and P(0,j) gives information related to column j.
I used a broad cast call:
MPI_Bcast(&row_data,1,MPI_INT,row_head,row_comm)
MPI_Bcast(&col_data,1,MPI_INT,col_head,col_comm)
Please find my code here: http://pastebin.com/NpqRWaWN
Here is the error I see:
* An error occurred in MPI_Bcast
on communicator MPI COMMUNICATOR 5 CREATE FROM 3
MPI_ERR_ROOT: invalid root
* MPI_ERRORS_ARE_FATAL (your MPI job will now abort)
Also please let me know if there is any better way to distribute the matrix data.
There are several errors in your program. First, row_Ranks is declared with one element less and when writing to it, you possibly overwrite other stack variables:
int col_Ranks[SIZE], row_Ranks[SIZE-1];
// ^^^^^^
On my test system the program just hangs because of that.
Second, you create new subcommunicators out of matrixComm but you use rank numbers from the latter to address processes in the former when performing the broadcast. That doesn't work. For example, in a 2x2 Cartesian communicator ranks range from 0 to 3. In any column- or row-wise subgroup there are only two processes with ranks 0 and 1 - there is neither rank 2 nor rank 3. If you take a look at the value of row_head across the ranks, it is 2 in two of them, hence the error.
For a much better way to distribute the data, you should refer to this extremely informative answer.

Resources