|  | @@ -1,9 +1,15 @@
 | 
	
		
			
			| 1 | 1 |  # coding: utf-8
 | 
	
		
			
			| 2 |  | -import os
 | 
	
		
			
			|  | 2 | +import ctypes
 | 
	
		
			
			|  | 3 | +import multiprocessing
 | 
	
		
			
			| 3 | 4 |  import psutil
 | 
	
		
			
			|  | 5 | +from multiprocessing import Manager
 | 
	
		
			
			|  | 6 | +from multiprocessing import Array
 | 
	
		
			
			| 4 | 7 |  
 | 
	
		
			
			|  | 8 | +import pytest
 | 
	
		
			
			|  | 9 | +
 | 
	
		
			
			|  | 10 | +from synergine2.config import Config
 | 
	
		
			
			| 5 | 11 |  from synergine2.processing import ProcessManager
 | 
	
		
			
			| 6 |  | -from synergine2.utils import ChunkManager
 | 
	
		
			
			|  | 12 | +from synergine2.share import SharedDataManager
 | 
	
		
			
			| 7 | 13 |  from tests import BaseTest
 | 
	
		
			
			| 8 | 14 |  
 | 
	
		
			
			| 9 | 15 |  available_cores = len(psutil.Process().cpu_affinity())
 | 
	
	
		
			
			|  | @@ -17,85 +23,135 @@ class MyFakeClass(object):
 | 
	
		
			
			| 17 | 23 |  class TestProcessing(BaseTest):
 | 
	
		
			
			| 18 | 24 |      def make_job_with_scalar(
 | 
	
		
			
			| 19 | 25 |              self,
 | 
	
		
			
			| 20 |  | -            data_chunk: list,
 | 
	
		
			
			| 21 |  | -            process_number: int,
 | 
	
		
			
			| 22 |  | -            process_count: int,
 | 
	
		
			
			| 23 |  | -    ) -> tuple:
 | 
	
		
			
			| 24 |  | -        current_pid = os.getpid()
 | 
	
		
			
			| 25 |  | -        result = sum(data_chunk)
 | 
	
		
			
			| 26 |  | -        return current_pid, result
 | 
	
		
			
			|  | 26 | +            data: list,
 | 
	
		
			
			|  | 27 | +    ):
 | 
	
		
			
			|  | 28 | +        result = sum(data)
 | 
	
		
			
			|  | 29 | +        return result
 | 
	
		
			
			| 27 | 30 |  
 | 
	
		
			
			| 28 | 31 |      def make_job_with_object(
 | 
	
		
			
			| 29 | 32 |              self,
 | 
	
		
			
			| 30 |  | -            data_chunk: list,
 | 
	
		
			
			| 31 |  | -            process_number: int,
 | 
	
		
			
			| 32 |  | -            process_count: int,
 | 
	
		
			
			| 33 |  | -    ) -> tuple:
 | 
	
		
			
			| 34 |  | -        current_pid = os.getpid()
 | 
	
		
			
			| 35 |  | -        data = [o.value for o in data_chunk]
 | 
	
		
			
			|  | 33 | +            data: list,
 | 
	
		
			
			|  | 34 | +    ):
 | 
	
		
			
			|  | 35 | +        data = [o.value for o in data]
 | 
	
		
			
			| 36 | 36 |          result = sum(data)
 | 
	
		
			
			| 37 |  | -        return current_pid, MyFakeClass(result)
 | 
	
		
			
			|  | 37 | +        return MyFakeClass(result)
 | 
	
		
			
			| 38 | 38 |  
 | 
	
		
			
			| 39 | 39 |      def test_parallel_jobs_with_scalar(self):
 | 
	
		
			
			| 40 |  | -        chunk_manager = ChunkManager(available_cores)
 | 
	
		
			
			| 41 | 40 |          process_manager = ProcessManager(
 | 
	
		
			
			|  | 41 | +            config=Config({}),
 | 
	
		
			
			| 42 | 42 |              process_count=available_cores,
 | 
	
		
			
			| 43 |  | -            chunk_manager=chunk_manager,
 | 
	
		
			
			|  | 43 | +            job=self.make_job_with_scalar,
 | 
	
		
			
			| 44 | 44 |          )
 | 
	
		
			
			| 45 | 45 |  
 | 
	
		
			
			| 46 | 46 |          data = list(range(100))
 | 
	
		
			
			| 47 |  | -        process_id_list = []
 | 
	
		
			
			| 48 |  | -        final_result = 0
 | 
	
		
			
			| 49 | 47 |  
 | 
	
		
			
			| 50 |  | -        results = process_manager.chunk_and_execute_jobs(
 | 
	
		
			
			| 51 |  | -            data,
 | 
	
		
			
			| 52 |  | -            job_maker=self.make_job_with_scalar,
 | 
	
		
			
			| 53 |  | -        )
 | 
	
		
			
			| 54 |  | -
 | 
	
		
			
			| 55 |  | -        for process_id, result in results:
 | 
	
		
			
			| 56 |  | -            final_result += result
 | 
	
		
			
			| 57 |  | -            process_id_list.append(process_id)
 | 
	
		
			
			|  | 48 | +        results = process_manager.make_them_work(data)
 | 
	
		
			
			|  | 49 | +        process_manager.terminate()
 | 
	
		
			
			| 58 | 50 |  
 | 
	
		
			
			| 59 |  | -        # Goal is 4950
 | 
	
		
			
			| 60 |  | -        assert final_result == 4950
 | 
	
		
			
			|  | 51 | +        assert sum(results) == 39600
 | 
	
		
			
			| 61 | 52 |  
 | 
	
		
			
			| 62 | 53 |      def test_non_parallel_jobs_with_scalar(self):
 | 
	
		
			
			| 63 |  | -        chunk_manager = ChunkManager(1)
 | 
	
		
			
			|  | 54 | +        # TODO: process manager utilise actuellement un cpu quand même, changer ca
 | 
	
		
			
			| 64 | 55 |          process_manager = ProcessManager(
 | 
	
		
			
			|  | 56 | +            config=Config({}),
 | 
	
		
			
			| 65 | 57 |              process_count=1,
 | 
	
		
			
			| 66 |  | -            chunk_manager=chunk_manager,
 | 
	
		
			
			|  | 58 | +            job=self.make_job_with_scalar,
 | 
	
		
			
			| 67 | 59 |          )
 | 
	
		
			
			| 68 | 60 |  
 | 
	
		
			
			| 69 | 61 |          data = list(range(100))
 | 
	
		
			
			| 70 |  | -        results = process_manager.chunk_and_execute_jobs(
 | 
	
		
			
			| 71 |  | -            data,
 | 
	
		
			
			| 72 |  | -            job_maker=self.make_job_with_scalar,
 | 
	
		
			
			| 73 |  | -        )
 | 
	
		
			
			| 74 |  | -        process_id, final_result = results[0]
 | 
	
		
			
			|  | 62 | +        results = process_manager.make_them_work(data)
 | 
	
		
			
			|  | 63 | +        process_manager.terminate()
 | 
	
		
			
			|  | 64 | +        final_result = results[0]
 | 
	
		
			
			| 75 | 65 |  
 | 
	
		
			
			| 76 | 66 |          assert len(results) == 1
 | 
	
		
			
			| 77 |  | -        assert process_id == os.getpid()
 | 
	
		
			
			| 78 | 67 |          assert final_result == 4950
 | 
	
		
			
			| 79 | 68 |  
 | 
	
		
			
			| 80 | 69 |      def test_parallel_jobs_with_objects(self):
 | 
	
		
			
			| 81 |  | -        chunk_manager = ChunkManager(available_cores)
 | 
	
		
			
			| 82 | 70 |          process_manager = ProcessManager(
 | 
	
		
			
			|  | 71 | +            config=Config({}),
 | 
	
		
			
			| 83 | 72 |              process_count=available_cores,
 | 
	
		
			
			| 84 |  | -            chunk_manager=chunk_manager,
 | 
	
		
			
			|  | 73 | +            job=self.make_job_with_object,
 | 
	
		
			
			| 85 | 74 |          )
 | 
	
		
			
			| 86 | 75 |  
 | 
	
		
			
			| 87 | 76 |          data = [MyFakeClass(v) for v in range(100)]
 | 
	
		
			
			| 88 |  | -        process_id_list = []
 | 
	
		
			
			| 89 | 77 |          final_result = 0
 | 
	
		
			
			| 90 | 78 |  
 | 
	
		
			
			| 91 |  | -        results = process_manager.chunk_and_execute_jobs(
 | 
	
		
			
			| 92 |  | -            data,
 | 
	
		
			
			| 93 |  | -            job_maker=self.make_job_with_object,
 | 
	
		
			
			| 94 |  | -        )
 | 
	
		
			
			|  | 79 | +        results = process_manager.make_them_work(data)
 | 
	
		
			
			|  | 80 | +        process_manager.terminate()
 | 
	
		
			
			| 95 | 81 |  
 | 
	
		
			
			| 96 |  | -        for process_id, result_object in results:
 | 
	
		
			
			|  | 82 | +        for result_object in results:
 | 
	
		
			
			| 97 | 83 |              final_result += result_object.value
 | 
	
		
			
			| 98 |  | -            process_id_list.append(process_id)
 | 
	
		
			
			| 99 | 84 |  
 | 
	
		
			
			| 100 |  | -        # Goal is 4950
 | 
	
		
			
			| 101 |  | -        assert final_result == 4950
 | 
	
		
			
			|  | 85 | +        assert final_result == 39600
 | 
	
		
			
			|  | 86 | +
 | 
	
		
			
			|  | 87 | +    def test_shared_memory_with_shared_manager(self):
 | 
	
		
			
			|  | 88 | +        shared = SharedDataManager()
 | 
	
		
			
			|  | 89 | +        shared.set('counter', 42)
 | 
	
		
			
			|  | 90 | +
 | 
	
		
			
			|  | 91 | +        def job(*args, **kwargs):
 | 
	
		
			
			|  | 92 | +            return shared.get('counter') + 1
 | 
	
		
			
			|  | 93 | +
 | 
	
		
			
			|  | 94 | +        process_manager = ProcessManager(
 | 
	
		
			
			|  | 95 | +            config=Config({}),
 | 
	
		
			
			|  | 96 | +            process_count=available_cores,
 | 
	
		
			
			|  | 97 | +            job=job,
 | 
	
		
			
			|  | 98 | +        )
 | 
	
		
			
			|  | 99 | +
 | 
	
		
			
			|  | 100 | +        results = process_manager.make_them_work(None)
 | 
	
		
			
			|  | 101 | +        process_manager.terminate()
 | 
	
		
			
			|  | 102 | +
 | 
	
		
			
			|  | 103 | +        assert results[0] == 43
 | 
	
		
			
			|  | 104 | +
 | 
	
		
			
			|  | 105 | +    def test_share_data_with_function(self):
 | 
	
		
			
			|  | 106 | +        shared = SharedDataManager()
 | 
	
		
			
			|  | 107 | +
 | 
	
		
			
			|  | 108 | +        class Foo(object):
 | 
	
		
			
			|  | 109 | +            counter = shared.create('counter', 0)
 | 
	
		
			
			|  | 110 | +
 | 
	
		
			
			|  | 111 | +        def job(*args, **kwargs):
 | 
	
		
			
			|  | 112 | +            return shared.get('counter') + 1
 | 
	
		
			
			|  | 113 | +
 | 
	
		
			
			|  | 114 | +        process_manager = ProcessManager(
 | 
	
		
			
			|  | 115 | +            config=Config({}),
 | 
	
		
			
			|  | 116 | +            process_count=available_cores,
 | 
	
		
			
			|  | 117 | +            job=job,
 | 
	
		
			
			|  | 118 | +        )
 | 
	
		
			
			|  | 119 | +
 | 
	
		
			
			|  | 120 | +        foo = Foo()
 | 
	
		
			
			|  | 121 | +        foo.counter = 42
 | 
	
		
			
			|  | 122 | +
 | 
	
		
			
			|  | 123 | +        results = process_manager.make_them_work(None)
 | 
	
		
			
			|  | 124 | +        assert results[0] == 43
 | 
	
		
			
			|  | 125 | +
 | 
	
		
			
			|  | 126 | +        foo.counter = 45
 | 
	
		
			
			|  | 127 | +
 | 
	
		
			
			|  | 128 | +        results = process_manager.make_them_work(None)
 | 
	
		
			
			|  | 129 | +        assert results[0] == 46
 | 
	
		
			
			|  | 130 | +
 | 
	
		
			
			|  | 131 | +        process_manager.terminate()
 | 
	
		
			
			|  | 132 | +
 | 
	
		
			
			|  | 133 | +    def test_after_created_shared_data(self):
 | 
	
		
			
			|  | 134 | +        shared = SharedDataManager()
 | 
	
		
			
			|  | 135 | +
 | 
	
		
			
			|  | 136 | +        shared.set('foo_1', 0)
 | 
	
		
			
			|  | 137 | +
 | 
	
		
			
			|  | 138 | +        def job(key):
 | 
	
		
			
			|  | 139 | +            return shared.get('foo_{}'.format(key)) + 1
 | 
	
		
			
			|  | 140 | +
 | 
	
		
			
			|  | 141 | +        process_manager = ProcessManager(
 | 
	
		
			
			|  | 142 | +            config=Config({}),
 | 
	
		
			
			|  | 143 | +            process_count=available_cores,
 | 
	
		
			
			|  | 144 | +            job=job,
 | 
	
		
			
			|  | 145 | +        )
 | 
	
		
			
			|  | 146 | +
 | 
	
		
			
			|  | 147 | +        shared.set('foo_1', 42)
 | 
	
		
			
			|  | 148 | +
 | 
	
		
			
			|  | 149 | +        results = process_manager.make_them_work('1')
 | 
	
		
			
			|  | 150 | +        assert results[0] == 43
 | 
	
		
			
			|  | 151 | +
 | 
	
		
			
			|  | 152 | +        shared.set('foo_2', 52)
 | 
	
		
			
			|  | 153 | +
 | 
	
		
			
			|  | 154 | +        results = process_manager.make_them_work('2')
 | 
	
		
			
			|  | 155 | +        assert results[0] == 53
 | 
	
		
			
			|  | 156 | +
 | 
	
		
			
			|  | 157 | +        process_manager.terminate()
 |