From 6ea3a2d4de68e13c0711ddbb41efb5e52b2eb32d Mon Sep 17 00:00:00 2001
From: huongdm1896 <domaihuong1451997@gmail.com>
Date: Mon, 24 Feb 2025 19:14:17 +0100
Subject: [PATCH] update 12 testcases in json

---
 Flower_v1/client_1.py     |  32 ++-
 Flower_v1/server_1.py     |  48 +++-
 README.md                 |  27 +-
 Run/config_instances.json | 560 +++++++++++++++++++++++++++++++++++++-
 Run/custom_gpuclock.py    |  67 ++---
 5 files changed, 661 insertions(+), 73 deletions(-)

diff --git a/Flower_v1/client_1.py b/Flower_v1/client_1.py
index ae28e95..af26d00 100644
--- a/Flower_v1/client_1.py
+++ b/Flower_v1/client_1.py
@@ -1,4 +1,4 @@
-#python3 client_1.py <dataset> <id> <total_client> <IP:PORT>
+#python3 client_1.py <dataset> <partition> <client_num> <IP:PORT>
 #python3 client_1.py cifar10 1 3 172.16.66.55:8080
 
 import flwr as fl
@@ -10,18 +10,33 @@ import sys
 # Function to load and partition the dataset based on client_id
 def load_partitioned_data(dataset_name, num_clients, client_id):
     if dataset_name == "cifar10":
+        '''
+        total samples train: 50000
+        total samples test: 10000
+        sample type: animals, vehicles, etc. 
+        '''
         (x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()
         x_train = x_train.astype("float32") / 255.0
         x_test = x_test.astype("float32") / 255.0
         num_classes = 10
         input_shape = (32, 32, 3)
     elif dataset_name == "mnist":
+        '''
+        total samples train: 60000
+        total samples test: 10000
+        sample type: handwritten digits
+        '''
         (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
         x_train = x_train.reshape(-1, 28, 28, 1).astype("float32") / 255.0
         x_test = x_test.reshape(-1, 28, 28, 1).astype("float32") / 255.0
         num_classes = 10
         input_shape = (28, 28, 1)
     elif dataset_name == "cifar100":
+        '''
+        total samples train: 50000
+        total samples test: 10000
+        sample type: animals, objects
+        '''
         (x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar100.load_data()
         x_train = x_train.astype("float32") / 255.0
         x_test = x_test.astype("float32") / 255.0
@@ -30,7 +45,7 @@ def load_partitioned_data(dataset_name, num_clients, client_id):
     else:
         raise ValueError("Dataset not supported. Use 'cifar10', 'mnist', or 'cifar100'.")
     
-    # Partition the dataset among the clients
+    # Partition the dataset among the clients (same data distribution with same number_clients setup)
     total_samples = x_train.shape[0]
     samples_per_client = total_samples // num_clients
 
@@ -39,6 +54,9 @@ def load_partitioned_data(dataset_name, num_clients, client_id):
 
     x_client_train = x_train[start:end]
     y_client_train = y_train[start:end]
+    
+    # x_client_train = x_train
+    # y_client_train = y_train
 
     # Split the client-specific data into training and validation sets
     x_train, x_val, y_train, y_val = train_test_split(x_client_train, y_client_train, test_size=0.2, random_state=42)
@@ -47,7 +65,7 @@ def load_partitioned_data(dataset_name, num_clients, client_id):
 
 # Get command-line arguments: dataset, client_id, num_clients, and server address
 if len(sys.argv) != 5:
-    print("Usage: python3 client.py <dataset> <partition> <client_num> <IP:PORT>")
+    print("Usage: python3 client_1.py <dataset> <partition> <client_num> <IP:PORT>")
     sys.exit(1)
 
 dataset_name = sys.argv[1]
@@ -69,17 +87,17 @@ class FederatedClient(fl.client.NumPyClient):
 
     def fit(self, parameters, config):
         model.set_weights(parameters)
-        model.fit(x_train, y_train, epochs=1, batch_size=32, validation_data=(x_val, y_val))
+        model.fit(x_train, y_train, epochs=5, batch_size=32, validation_data=(x_val, y_val))
         return model.get_weights(), len(x_train), {}
 
     def evaluate(self, parameters, config):
         model.set_weights(parameters)
-        loss, accuracy = model.evaluate(x_test, y_test)
+        loss, accuracy = model.evaluate(x_test, y_test, verbose=0)
         return loss, len(x_test), {"accuracy": float(accuracy)}
 
 # Start Flower client
 if __name__ == "__main__":
     fl.client.start_client(server_address=server_address, 
                            client=FederatedClient(),
-                           max_retries=5,
-                           max_wait_time=10)
+                           max_retries=3, # retry connection to server 3 times
+                           max_wait_time=5) # wait 5 seconds before retrying
diff --git a/Flower_v1/server_1.py b/Flower_v1/server_1.py
index a466496..a2ca18e 100644
--- a/Flower_v1/server_1.py
+++ b/Flower_v1/server_1.py
@@ -8,7 +8,7 @@ from flwr.server.strategy import Strategy
 from flwr.server.client_manager import ClientManager
 from flwr.server.client_proxy import ClientProxy
 from flwr.server import ServerApp, ServerConfig
-from flwr.server.strategy import FedAvg, FedMedian, FedOpt, FedAdam
+from flwr.server.strategy import FedAvg, FedMedian, FedOpt, FedAdam, FedProx, QFedAvg
 import argparse
 import tensorflow as tf
 import flwr
@@ -110,8 +110,8 @@ parser.add_argument(
     "--strategy",
     type=str,
     default="fedAvg",
-    choices=["fedAvg", "fedMedian", "fedOpt", "fedAdam", "fedAvg2Clients"],  # Add options strategies
-    help="Select strategy: fedAvg, fedMedian, fedOpt or fedAdam or fedAvg2Clients",
+    choices=["fedAvg", "fedMedian", "fedOpt", "fedAdam", "fedAvg2Clients", "fedProx", "QfedAvg"],  # Add options strategies
+    help="Select strategy: fedAvg, fedMedian, fedOpt, fedAdam, fedProx, QfedAvg or fedAvg2Clients",
 )
 
 parser.add_argument("-l", "--log_dir", type=str, default=None, help="Directory to save logs")
@@ -141,24 +141,46 @@ weights = model.get_weights()
 parameters = flwr.common.ndarrays_to_parameters(weights)
 
 # Select the base strategy
-if args.strategy == "fedAvg":
-    base_strategy = FedAvg(evaluate_metrics_aggregation_fn=weighted_average)
-elif args.strategy == "fedAvg2Clients":
+if args.strategy == "fedAvg": 
+    # baseline strategy
     base_strategy = FedAvg(
-        fraction_fit=0.67,
-        min_fit_clients=2,
-        min_available_clients=2,
+        evaluate_metrics_aggregation_fn=weighted_average)
+elif args.strategy == "fedAvg2Clients": 
+    # Custom client num each round
+    base_strategy = FedAvg(
+        fraction_fit=0.67, # 67% of clients agg/fit each round
+        min_fit_clients=2, # At least 2 clients fit each round
+        min_available_clients=2, # At least 2 clients available each round
         evaluate_metrics_aggregation_fn=weighted_average,
     )
 elif args.strategy == "fedMedian":
-    base_strategy = FedMedian(evaluate_metrics_aggregation_fn=weighted_average)
-elif args.strategy == "fedOpt":
+    # robustness strategy
+    base_strategy = FedMedian(
+        evaluate_metrics_aggregation_fn=weighted_average)
+elif args.strategy == "fedOpt": 
+    # server optimization strategy
     base_strategy = FedOpt(
-        evaluate_metrics_aggregation_fn=weighted_average, initial_parameters=parameters
+        evaluate_metrics_aggregation_fn=weighted_average, 
+        initial_parameters=parameters
     )
 elif args.strategy == "fedAdam":
+    # server optimization strategy use Adam
     base_strategy = FedAdam(
-        evaluate_metrics_aggregation_fn=weighted_average, initial_parameters=parameters
+        evaluate_metrics_aggregation_fn=weighted_average, 
+        initial_parameters=parameters
+    )
+elif args.strategy == "fedProx":
+    # regularization strategy
+    base_strategy = FedProx(
+        evaluate_metrics_aggregation_fn=weighted_average, 
+        initial_parameters=parameters,
+        proximal_mu = 0.1
+    )
+elif args.strategy == "QFedAvg":
+    # improve fairness, reduce var_loss strategy
+    base_strategy = QFedAvg(
+        evaluate_metrics_aggregation_fn=weighted_average, 
+        initial_parameters=parameters
     )
 
 
diff --git a/README.md b/README.md
index 4044019..62c3af3 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ This project provides tools to measure the energy consumption of Flower-based fe
 - [Usage](#usage)
   - [FL framework](#fl-framework)
   - [Configure instances for CPU](#configure-instance-for-cpu)
-  - [Configure instances for GPU](#configure-instance-for-gpu)
+  - [Configure instances for GPU](#configure-instance-for-gpu-developing)
   - [Run exp](#run-exp)
 - [Quickstart](#quickstart)
   - [Step 1. Reserve the Hosts in G5K](#step-1-reserve-the-hosts-in-g5k)
@@ -69,7 +69,7 @@ Configure instances of experiment in a json format, structure is shown below.
       ```bash
       bash "$(python3 -c "import expetator, os; print(os.path.join(os.path.dirname(expetator.__file__), 'leverages', 'dvfs_pct.sh'))")" init
       ```
-      - Run this command to get available frequencies:
+      - Run this command to get available 4 frequencies (min, max, 2 in middle):
       ```bash
       python3 get_frequencies.py
       ```
@@ -114,15 +114,26 @@ Configure instances of experiment in a json format, structure is shown below.
     }
     ```
 
-### Configure instance for GPU
+### Configure instance for GPU (*developing)
 
 - The configuration is as same CPU, except **dvfs** role. In GPU config, the role is **dvfs_gpu**.  
-Choose only one in 3 settings (steps - zoomfrom - zoomto use for one setting).
+Choose only one in 3 settings:
     - `dummy`: for testing in min and max GPU freq (`false` or `true`).
     - `baseline`: for testing in max GPU freq (`false` or `true`).
-    - `steps`: steps to jump in range/window of frequencies (int).
-    - `zoomfrom`: freq start
-    - `zoomto`: freq stop
+    - last setting includes 3 parameters: test with the all freqs in the range. To disable this setting, set the `zoomfrom` and `zoomto` are same values.  
+      - `steps`: steps to jump in range/window of frequencies (int).  
+      - `zoomfrom`: freq start  
+      - `zoomto`: freq stop  
+    *example:*  
+        - list of freq available [1, 1.1, 1.2, 1.9, 2.5, 2.7] GHz  
+        - with `zoomfrom` = 1.1, `zoomto` = 2.7 and `steps` = 2  
+        - list of tested freq returns [1.1, 1.9, 2,7]  
+
+    **Remark:** check the available frequencies before using option `frequencies`.
+    Run below cmd:
+    ```bash
+    nvidia-smi -i 0 --query-supported-clocks=gr --format=csv,noheader,nounits | tr '\n' ' '
+    ```
 
   ```json
   "dvfs_gpu": {
@@ -169,6 +180,8 @@ Reserve 4 hosts (GPU) (1 server + 3 clients) for 2 hours:
 oarsub -I -t exotic -p "gpu_count>0" -l {"cluster='drac'"}/host=4 # grenoble
 ```
 
+**Remark**: for now only 2 clusters, `chifflot` in Lille and `drac` in Grenoble are available for testing in more than 3 GPU nodes, maximum is 8 (`chifflot`) or 12 (`drac`) nodes.
+
 Make sure your are in`eflwr/Run/`:
 ```bash
 cd Run
diff --git a/Run/config_instances.json b/Run/config_instances.json
index 941ec5d..b8bac0b 100644
--- a/Run/config_instances.json
+++ b/Run/config_instances.json
@@ -4,7 +4,7 @@
             "instance": "fedAvg_cifar10",
             "output_dir": "./Log",
             "dvfs_cpu": {
-                "dummy": true,
+                "dummy": false,
                 "baseline": false,
                 "frequencies": null
             },
@@ -26,7 +26,7 @@
                 "args": [
                     "./Flower_v1/client_1.py",
                     "cifar10",
-                    "1",
+                    "0",
                     "3"
                 ],
                 "ip": "172.16.66.77"
@@ -37,7 +37,7 @@
                 "args": [
                     "./Flower_v1/client_1.py",
                     "cifar10",
-                    "2",
+                    "1",
                     "3"
                 ],
                 "ip": "172.16.66.78"
@@ -48,7 +48,7 @@
                 "args": [
                     "./Flower_v1/client_1.py",
                     "cifar10",
-                    "3",
+                    "2",
                     "3"
                 ],
                 "ip": "172.16.66.79"
@@ -56,6 +56,116 @@
             ]
         },
         "2": {
+            "instance": "fedAvg_cifar100",
+            "output_dir": "./Log",
+            "dvfs_cpu": {
+                "dummy": true,
+                "baseline": false,
+                "frequencies": null
+            },
+            "server": {
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/server_1.py",
+                    "-r 1",
+                    "-s fedAvg"
+                ],
+                "ip": "172.16.66.76",
+                "modules": ["logger"],
+                "port": 8080
+            },
+            "clients": [
+            {
+                "name": "client1",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar100",
+                    "0",
+                    "3"
+                ],
+                "ip": "172.16.66.77"
+            },
+            {
+                "name": "client2",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar100",
+                    "1",
+                    "3"
+                ],
+                "ip": "172.16.66.78"
+            },
+            {
+                "name": "client3",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar100",
+                    "2",
+                    "3"
+                ],
+                "ip": "172.16.66.79"
+            }
+            ]
+        },
+        "3": {
+            "instance": "fedAvg_mnist",
+            "output_dir": "./Log",
+            "dvfs_cpu": {
+                "dummy": true,
+                "baseline": false,
+                "frequencies": null
+            },
+            "server": {
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/server_1.py",
+                    "-r 1",
+                    "-s fedAvg"
+                ],
+                "ip": "172.16.66.76",
+                "modules": ["logger"],
+                "port": 8080
+            },
+            "clients": [
+            {
+                "name": "client1",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "mnist",
+                    "0",
+                    "3"
+                ],
+                "ip": "172.16.66.77"
+            },
+            {
+                "name": "client2",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "mnist",
+                    "1",
+                    "3"
+                ],
+                "ip": "172.16.66.78"
+            },
+            {
+                "name": "client3",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "mnist",
+                    "2",
+                    "3"
+                ],
+                "ip": "172.16.66.79"
+            }
+            ]
+        },
+        "4": {
             "instance": "fedAvg2Clients_cifar10",
             "output_dir": "./Log",
             "dvfs_cpu": {
@@ -78,12 +188,177 @@
             {
                 "name": "client1",
                 "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar10",
+                    "0",
+                    "3"
+                ],
+                "ip": "172.16.66.77"
+            },
+            {
+                "name": "client2",
+                "command": "python3",
                 "args": [
                     "./Flower_v1/client_1.py",
                     "cifar10",
                     "1",
                     "3"
                 ],
+                "ip": "172.16.66.78"
+            },
+            {
+                "name": "client3",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar10",
+                    "2",
+                    "3"
+                ],
+                "ip": "172.16.66.79"
+            }
+            ]
+        },
+        "5": {
+            "instance": "fedAvg2Clients_cifar100",
+            "output_dir": "./Log",
+            "dvfs_cpu": {
+                "dummy": true,
+                "baseline": false,
+                "frequencies": null
+            },
+            "server": {
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/server_1.py",
+                    "-r 1",
+                    "-s fedAvg2Clients"
+                ],
+                "ip": "172.16.66.76",
+                "modules": ["logger"],
+                "port": 8080
+            },
+            "clients": [
+            {
+                "name": "client1",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar100",
+                    "0",
+                    "3"
+                ],
+                "ip": "172.16.66.77"
+            },
+            {
+                "name": "client2",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar100",
+                    "1",
+                    "3"
+                ],
+                "ip": "172.16.66.78"
+            },
+            {
+                "name": "client3",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar100",
+                    "2",
+                    "3"
+                ],
+                "ip": "172.16.66.79"
+            }
+            ]
+        },
+        "6": {
+            "instance": "fedAvg2Clients_mnist",
+            "output_dir": "./Log",
+            "dvfs_cpu": {
+                "dummy": true,
+                "baseline": false,
+                "frequencies": null
+            },
+            "server": {
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/server_1.py",
+                    "-r 1",
+                    "-s fedAvg2Clients"
+                ],
+                "ip": "172.16.66.76",
+                "modules": ["logger"],
+                "port": 8080
+            },
+            "clients": [
+            {
+                "name": "client1",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "mnist",
+                    "0",
+                    "3"
+                ],
+                "ip": "172.16.66.77"
+            },
+            {
+                "name": "client2",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "mnist",
+                    "1",
+                    "3"
+                ],
+                "ip": "172.16.66.78"
+            },
+            {
+                "name": "client3",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "mnist",
+                    "2",
+                    "3"
+                ],
+                "ip": "172.16.66.79"
+            }
+            ]
+        },
+        "7": {
+            "instance": "fedProx_cifar10",
+            "output_dir": "./Log",
+            "dvfs_cpu": {
+                "dummy": true,
+                "baseline": false,
+                "frequencies": null
+            },
+            "server": {
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/server_1.py",
+                    "-r 1",
+                    "-s fedProx"
+                ],
+                "ip": "172.16.66.76",
+                "modules": ["logger"],
+                "port": 8080
+            },
+            "clients": [
+            {
+                "name": "client1",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar10",
+                    "0",
+                    "3"
+                ],
                 "ip": "172.16.66.77"
             },
             {
@@ -92,18 +367,293 @@
                 "args": [
                     "./Flower_v1/client_1.py",
                     "cifar10",
+                    "1",
+                    "3"
+                ],
+                "ip": "172.16.66.78"
+            },
+            {
+                "name": "client3",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar10",
+                    "2",
+                    "3"
+                ],
+                "ip": "172.16.66.79"
+            }
+            ]
+        },
+        "8": {
+            "instance": "fedProx_cifar100",
+            "output_dir": "./Log",
+            "dvfs_cpu": {
+                "dummy": true,
+                "baseline": false,
+                "frequencies": null
+            },
+            "server": {
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/server_1.py",
+                    "-r 1",
+                    "-s fedProx"
+                ],
+                "ip": "172.16.66.76",
+                "modules": ["logger"],
+                "port": 8080
+            },
+            "clients": [
+            {
+                "name": "client1",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar100",
+                    "0",
+                    "3"
+                ],
+                "ip": "172.16.66.77"
+            },
+            {
+                "name": "client2",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar100",
+                    "1",
+                    "3"
+                ],
+                "ip": "172.16.66.78"
+            },
+            {
+                "name": "client3",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar100",
                     "2",
                     "3"
                 ],
+                "ip": "172.16.66.79"
+            }
+            ]
+        },
+        "9": {
+            "instance": "fedProx_mnist",
+            "output_dir": "./Log",
+            "dvfs_cpu": {
+                "dummy": true,
+                "baseline": false,
+                "frequencies": null
+            },
+            "server": {
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/server_1.py",
+                    "-r 1",
+                    "-s fedProx"
+                ],
+                "ip": "172.16.66.76",
+                "modules": ["logger"],
+                "port": 8080
+            },
+            "clients": [
+            {
+                "name": "client1",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "mnist",
+                    "0",
+                    "3"
+                ],
+                "ip": "172.16.66.77"
+            },
+            {
+                "name": "client2",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "mnist",
+                    "1",
+                    "3"
+                ],
                 "ip": "172.16.66.78"
             },
             {
                 "name": "client3",
                 "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "mnist",
+                    "2",
+                    "3"
+                ],
+                "ip": "172.16.66.79"
+            }
+            ]
+        },
+        "10": {
+            "instance": "fedAdam_cifar10",
+            "output_dir": "./Log",
+            "dvfs_cpu": {
+                "dummy": true,
+                "baseline": false,
+                "frequencies": null
+            },
+            "server": {
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/server_1.py",
+                    "-r 1",
+                    "-s fedAdam"
+                ],
+                "ip": "172.16.66.76",
+                "modules": ["logger"],
+                "port": 8080
+            },
+            "clients": [
+            {
+                "name": "client1",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar10",
+                    "0",
+                    "3"
+                ],
+                "ip": "172.16.66.77"
+            },
+            {
+                "name": "client2",
+                "command": "python3",
                 "args": [
                     "./Flower_v1/client_1.py",
                     "cifar10",
-                    "3",
+                    "1",
+                    "3"
+                ],
+                "ip": "172.16.66.78"
+            },
+            {
+                "name": "client3",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar10",
+                    "2",
+                    "3"
+                ],
+                "ip": "172.16.66.79"
+            }
+            ]
+        },
+        "11": {
+            "instance": "fedAdam_cifar100",
+            "output_dir": "./Log",
+            "dvfs_cpu": {
+                "dummy": true,
+                "baseline": false,
+                "frequencies": null
+            },
+            "server": {
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/server_1.py",
+                    "-r 1",
+                    "-s fedAdam"
+                ],
+                "ip": "172.16.66.76",
+                "modules": ["logger"],
+                "port": 8080
+            },
+            "clients": [
+            {
+                "name": "client1",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar100",
+                    "0",
+                    "3"
+                ],
+                "ip": "172.16.66.77"
+            },
+            {
+                "name": "client2",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar100",
+                    "1",
+                    "3"
+                ],
+                "ip": "172.16.66.78"
+            },
+            {
+                "name": "client3",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "cifar100",
+                    "2",
+                    "3"
+                ],
+                "ip": "172.16.66.79"
+            }
+            ]
+        },        
+        "12": {
+            "instance": "fedAdam_mnist",
+            "output_dir": "./Log",
+            "dvfs_cpu": {
+                "dummy": true,
+                "baseline": false,
+                "frequencies": null
+            },
+            "server": {
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/server_1.py",
+                    "-r 1",
+                    "-s fedAdam"
+                ],
+                "ip": "172.16.66.76",
+                "modules": ["logger"],
+                "port": 8080
+            },
+            "clients": [
+            {
+                "name": "client1",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "mnist",
+                    "0",
+                    "3"
+                ],
+                "ip": "172.16.66.77"
+            },
+            {
+                "name": "client2",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "mnist",
+                    "1",
+                    "3"
+                ],
+                "ip": "172.16.66.78"
+            },
+            {
+                "name": "client3",
+                "command": "python3",
+                "args": [
+                    "./Flower_v1/client_1.py",
+                    "mnist",
+                    "2",
                     "3"
                 ],
                 "ip": "172.16.66.79"
diff --git a/Run/custom_gpuclock.py b/Run/custom_gpuclock.py
index 952efb2..4046de7 100644
--- a/Run/custom_gpuclock.py
+++ b/Run/custom_gpuclock.py
@@ -1,10 +1,7 @@
-from expetator.leverages.gpuclock import GpuClock
 
-class CustomGpuClock(GpuClock):
-    """ Custom GPU Clock Leverage using clocks.gr instead of clocks.applications.gr """
-    
+class GpuClock:
+    'nvidia-smi graphics/sm clock setting'
     def __init__(self, dummy=False, baseline=False, steps=2, zoomfrom=0, zoomto=0):
-        super().__init__()
         self.dummy = dummy
         self.baseline = baseline
         self.executor = None
@@ -12,74 +9,62 @@ class CustomGpuClock(GpuClock):
         self.available_frequencies_mem = []
         self.clock_mem_max = None
         self.clock_sm_min = None
-        self.nsteps = steps  
-        
-        # Zoom enables fine granularity within a frequency window
+        self.nsteps = steps 
+        # zoomfrom/to enables full freq. granularity within a clock window:
         if zoomto != 0 and zoomfrom != zoomto:
             self.zoom = (zoomfrom, zoomto)
         else:
             self.zoom = None
 
     def build(self, executor):
-        """ Gather the available frequencies """
+        'Gather the available frequencies'
         self.executor = executor
         q = "nvidia-smi -i 0 --query-supported-clocks=gr --format=csv,noheader,nounits | tr '\n' ' '"
         clk_s = self.executor.local(q)
-        clk = sorted([int(f) for f in clk_s.strip().split() if f.isdigit()])
-        
-        if not clk:
-            raise RuntimeError("Failed to retrieve supported GPU clock frequencies.")
-
+        clk = sorted([int(f) for f in clk_s.strip().split(' ')])
         self.clock_sm_min = clk[0]
-        self.available_frequencies = [clk[(i * (len(clk) - 1)) // (self.nsteps - 1)] for i in range(self.nsteps)]
-        
+        self.available_frequencies = [clk[(i*(len(clk)-1))//(self.nsteps-1)] for i in range(self.nsteps)]
         q = "nvidia-smi -i 0 --query-supported-clocks=mem --format=csv,noheader,nounits | tr '\n' ' '"
         clk_s = self.executor.local(q)
-        self.available_frequencies_mem = sorted([int(f) for f in clk_s.strip().split() if f.isdigit()])
+        self.available_frequencies_mem = sorted([int(f) for f in clk_s.strip().split(' ')])
         self.clock_mem_max = self.available_frequencies_mem[-1]
-
-        if self.zoom:
-            clkz = [f for f in clk if self.zoom[0] <= f <= self.zoom[1]]
-            rest = [f for f in self.available_frequencies if f < self.zoom[0] or f > self.zoom[1]]
+        if self.zoom is not None:
+            # pick all available freq within the zoom window:
+            clkz = [f for f in clk if self.zoom[0] <= f and f <= self.zoom[1]]
+            rest = [f for f in self.available_frequencies if f < self.zoom[0] or self.zoom[1] < f]
             self.available_frequencies = sorted(clkz + rest)
-
         if self.dummy:
             self.available_frequencies = [self.available_frequencies[0], self.available_frequencies[-1]]
-
         if self.baseline:
             self.available_frequencies = [self.available_frequencies[-1]]
 
     def available_states(self):
-        """ Returns all available frequencies """
+        'Returns all the frequencies'
         return self.available_frequencies
 
     def start(self, freq):
-        """ Sets the GPU frequency """
+        'Sets the right frequency range on gpu 0'
         if freq in self.available_frequencies:
-            self.executor.local(f'nvidia-smi -i 0 -ac {self.clock_mem_max},{freq}', root=True)
+            self.executor.local('nvidia-smi -i 0 -ac  %s,%s' % (self.clock_mem_max, freq), root=True)
+            #self.executor.local('nvidia-smi -i 0 -lgc  %s,%s' % (self.clock_sm_min, freq), root=True)
 
     def stop(self, output_file=None):
-        """ Reset GPU to default frequency """
+        'Reverts to the maximum frequency'
         self.executor.local('nvidia-smi -i 0 -rac', root=True)
-
+        #self.executor.local('nvidia-smi -i 0 -rgc', root=True)
+            
     def get_state(self):
-        """ Returns the current min and max application frequencies using clocks.gr instead of clocks.applications.gr """
+        'Returns the current min and max application frequencies'
         cur_min = self.clock_sm_min
-        cur_max_str = self.executor.local('nvidia-smi -i 0 --query-gpu=clocks.gr --format=csv,noheader,nounits').strip()
-
-        try:
-            cur_max = int(cur_max_str)
-        except ValueError:
-            cur_max = 0  # Fallback in case of an error
-
-        return cur_min, cur_max, self.clock_mem_max
+        cur_max = int(self.executor.local('nvidia-smi -i 0 --query-gpu=clocks.applications.gr --format=csv,noheader,nounits'))
+        return (cur_min, cur_max, self.clock_mem_max)
 
     def state_to_str(self):
-        """ Returns the current min and max frequencies as a string """
-        cur_min, cur_max, mem_max = self.get_state()
-        return f'{cur_min} {cur_max} {mem_max}'
+        'Returns the current min and max frequencies as a string'
+        (cur_min, cur_max, mem_max) = self.get_state()
+        return '%s %s %s' % (cur_min, cur_max, mem_max)
 
     def get_labels(self):
-        """ Returns labels for frequencies """
+        'Returns the label for frequencies'
         return ('fmin', 'fmax', 'fmemax')
 
-- 
GitLab