## 5 Application of the Approach and Experimental Results  
In this Section we are going to show how we have applied our approach by using a specific parallel primitive, and we confront the results obtained taking by running the parallelized code on two Raspberry PIs and the sequential code on a centralized server, acting as a Gateway. In particular, we have focused on the parallelization of a Clustering algorithm, which is executed on a single device (the Home Gateway) in the current CoSSmic scenario. In the following, we will use Python as a reference programming language. The sequential program run on the Gateway is simply started through the execution of a _compute_cluster_ function, whose signature is as follows:  
_compute_cluster(run, data, history)_ where **run** is the maximum number of consecutive iterations the clusterization algorithm can run before stopping and giving a result, **data** is a reference to the data to be analyzed and **history** reports the cluster configuration obtained at the previous run. The algorithms has been built in order to be embarrassingly parallel, so a data or task parallel region can be immediately adopted. As shown in Listing 1 we first provide a definition of the Task Parallel primitive, then we pass the arguments which should be fed to the clusterization function to a **parser** in order to format and prepare them for the parallel execution. Such arguments are necessary to execute the parallel function and to correctly and store the input/output data. Finally we simply recall the Task Parallel Region primitive using the function to be parallelized as one of its arguments. ```
definfinitionoftheprimitive deftask_parallel_docker(items,docker,func,*args): avg=len(items)/float(docker) out=[] last=0.0 whilelast<len(items): out.append(items[int(last):int(last+avg)]) last+=avg return[func(x,*args)forxinout]
```  
```
def_name_==\"_main_\": start=time.time()
```usage=\"usage:\"_%prog[options]_filename\" parser=ArgumentParser(usage) parser.add_argument(\"filename\",metavar=\"FILENAME\") parser.add_argument(\"-r\",\"--runs\",default=0, dest=\"runs\",metavar=\"RUNS\",type=int, help=\"number_%of_\(\
u\)runs\") parser.add_argument(\"-d\",\"--docker\",default=0, dest=\"docker\",metavar=\"DOCKER\",type=int, help=\"number_%of_\(\omega\)dockers\") parser.add_argument(\"-n\",\"--history\",default=0, dest=\"history\",metavar=\"RUNID\",type=int, help=\"number_%of_\(\omega\)timeseries_\(\omega\)for_\(\omega\)clustering\") data_dir=\"./paper_data\" args=parser.parse_args() history=args.historyfilename=args.filename docker=args.docker  
task_parallel_docker(list(range(args.runs)),docker,compute_cluster, filename,history) ```
Listing 2: Master and Slave configurations. The Yaml configuration used to set-up the Dockers running on the final device has been provided in Listing 2. In the proposed configuration, one master and 4 slaves have been taken in consideration. The provided code only reports the configuration of the master and of one of the slaves, as they are all identical. In particular, the instructions that will be executed by the master and the slaves are included in two python files, which will be, in the future, automatically produced by a parser. ``` master:build:. depends_on: -redis command:python/fog/docker_master.py volumes: -type:bind source:./ target:/fog networks: redis-network: ipv4_address: stdin_open:true try:true ```
Listing 3: Master and Slave configurations. ``` master:build:. depends_on: -redis command:python/fog/docker_master.py volumes: -type:bind source:./ target:/fog networks: redis-network: ipv4_address: stdin_open:true try:true ```
Listing 4: Master and Slave configurations. ``` master:volumes: - type: bind source:./ target: /fog networks: - redis-network stdin_open: true try: true ```  
The Dockers will run on the target environment simultaneously, being it a Raspberry or the centralized server. Considering the Raspberries, each of the Dockers will run on a different virtual CPU.