Multiprocessor

Parallel Code Examples

Example 1

The contract ParaNativeAssignmentTest contains a function call() that utilizes the Multiprocess contract to execute the function assigner() in parallel. The assigner() function takes an input v and assigns the value v + 10 to the element at index v in the results array.

Here's a step-by-step explanation of what happens:

  1. The call() function is called, and it creates a new instance of the Multiprocess contract with 2 threads (processes).

  2. Two messages are pushed into the Multiprocess container with the function signature "assigner(uint256)" and respective values 0 and 1.

  3. The mp.run() function is called, which executes the two messages in parallel using the specified number of threads (2).

contract ParaNativeAssignmentTest {
    uint256[2] results;
    function call() public  { 
       Multiprocess mp = new Multiprocess(2); 
       mp.push(50000, address(this), abi.encodeWithSignature("assigner(uint256)", 0));
       mp.push(50000, address(this), abi.encodeWithSignature("assigner(uint256)", 1));
       mp.run();
    }

    function assigner(uint256 v)  public {
        results[v] = v + 10;
    }
} 

Analysis

The final result of results[0] will be 10, and the final result of results[1] will be 11. This is because the assigner() function is executed twice, once with v as 0, which assigns 0 + 10 = 10 to results[0], and once with v as 1, which assigns 1 + 10 = 11 to results[1]


Example 2

the NativeStorageAssignmentTest contract demonstrates how to use the Multiprocess contract to execute multiple tasks concurrently on a shared instance of the NativeStorage contract, allowing for efficient parallel processing. The end result of calling the call() function should be that results.getX() returns 2 and results.getY() returns 102.

contract NativeStorage {   
    uint256 public x = 1 ;
    uint256 public y = 100 ;

    function incrementX() public {x ++;}
    function incrementY() public {y += 2;}

    function getX() public view returns(uint256) {return x;}
    function getY() public view returns(uint256) {return y;}
}

contract NativeStorageAssignmentTest {
    NativeStorage results = new NativeStorage() ;
    function call() public  { 
        Multiprocess mp = new Multiprocess(2); 
        mp.push(50000, address(results), abi.encodeWithSignature("incrementX()"));
        mp.push(50000, address(results), abi.encodeWithSignature("incrementY()"));
        mp.run();
        require(results.getX() == 2);
        require(results.getY() == 102);
    }
}

Example 3

The third example is quite similar to the previous example. They both use the NativeStorage contract and the Arcology's concurrency framework to perform parallel execution of tasks. The only difference is that this example calls the incrementX() twice in parallel.

The incrementX() function inside the NativeStorage contract increases the value of the x variable by 1.

Since the two instances of NativeStorageAssignmentTest are running in parallel, they both attempt to modify the x and Y variable simultaneously. Arcology's concurrency framework detects the conflict. Only one of the modifications will succeed, and the other one will fail.

contract NativeStorage {   
    uint256 public x = 1 ;
    uint256 public y = 100 ;

    function incrementX() public {x ++;}
    function incrementY() public {y += 2;}

    function getX() public view returns(uint256) {return x;}
    function getY() public view returns(uint256) {return y;}
}

contract NativeStorageAssignmentTest {
    NativeStorage results = new NativeStorage() ;
    function call() public  { 
        Multiprocess mp = new Multiprocess(2); 
        mp.push(50000, address(results), abi.encodeWithSignature("incrementX()"));
        mp.push(50000, address(results), abi.encodeWithSignature("incrementX()"));
        mp.push(50000, address(results), abi.encodeWithSignature("incrementY()"));  
        mp.run();
        require(results.getX() == 2);
        require(results.getY() == 102);
    }
}

Analysis

As a result, after both calls to incrementX() are executed in parallel, the value of x will increase by 1, not 2. This is because one of the incrementX() calls and one of the calls succeeded, while the others failed due to conflicts.

Arcology ensures data consistency and integrity when concurrent operations are performed on shared state variables, allowing developers to harness the power of parallel execution without worrying about data corruption or conflicts.

Last updated