An ML-based Task offloading Framework for Energy-Efficient Fog Computing in IIoT Smart Applications
With the rapid expansion of Industrial Internet of Things (IIoT) applications, energy consumption and delay-sensitive task offloading remain major concerns, particularly in fog computing environments. This research addresses the critical and growing challenges of energy consumption and task offloading within the expanding realm of the Industrial Internet of Things (IIoT). Despite advancements in fog and cloud computing, a significant gap exists in traditional offloading strategies that fail to meet better performance due to long-distance data transmission. There is also a need for more intelligent mechanisms for task prioritization, efficient transmission scheduling, and dynamic adaptation to fluctuating network conditions. To address these limitations, this study evaluated the effectiveness of the ML-based approach, a predictive task offloading system designed for an IoT environment. ML-based task offloading integrates a supervised machine learning algorithm to offload tasks based on device capabilities dynamically. Thus offering a viable solution to task offloading with minimal energy and maximum throughput.
Through extensive experiments on IoT data sets, the study assessed ML-based offloading and found that it outperformed baseline strategies. The results demonstrated that the ML-based approach achieved a high accuracy of 92% and a performance of 10-15% over baseline approaches.
The implications of these findings are substantial for the design and deployment of future IIoT systems. This research contributes valuable insights into creating "green" IIoT systems that improve Quality of Service (QoS) by meeting stringent energy constraints by illustrating the effective integration of machine learning models for intelligent resource management and task offloading in fog-cloud environments. This work provides a foundation for developing more sustainable and efficient industrial automation and innovative environmental solutions.
-
Internet of Things (IoT) has rapidly transformed various industries, including smart cities, healthcare, and more.
-
The Industrial Internet of Things (IIoT) extends these benefits to industrial applications, revolutionizing manufacturing, supply chain management, and industrial processes through automation.
-
A compelling business use case in the IIoT space comes from a smart city project in the Netherlands, where streetlights are intelligently controlled based on real-time needs — such as traffic movement or pedestrian presence.
-
The demand for IIoT solutions includes:
- Reduced downtime
- Increased productivity
- Optimized resource utilization
-
Value at Stake: A recent Cisco study estimated that applying IIoT in five business areas has the potential to deliver $14.4 trillion in value for private-sector companies, driven by cost savings and increased revenue through IIoT strategies.
-
Key factors influencing IIoT performance include:
- Latency
- Energy consumption
- Scalability
-
Challenges in traditional cloud-based architectures:
- Decision delays due to the large volume of data generated by IIoT devices
-
Offloading plays a vital role by transferring data processing to resource-rich remote devices.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import joblib
import random
class ExecutionEnvironment:
def __init__(self, id, computation_capacity, frequency, transmission_rate):
self.__id = id
self.__computation_capacity = computation_capacity
self.__frequency = frequency
self.__transmission_rate = transmission_rate
def get_id(self):
return self.__id
def get_computation_capacity(self):
return self.__computation_capacity
def get_frequency(self):
return self.__frequency
def get_transmission_rate(self):
return self.__transmission_rate
class Device:
def __init__(self, id, computation_capacity, frequency):
self.__id = id
self.__computation_capacity = computation_capacity
self.__frequency = frequency
def get_id(self):
return self.__id
def get_frequency(self):
return self.__frequency
class IIoTSystem:
def __init__(self, num_iot_devices, num_fog_devices, num_cloud_servers, D, bandwidth, K_k_in_range, lambda_k_range):
self.num_iot_devices = num_iot_devices
self.num_fog_devices = num_fog_devices
self.num_cloud_servers = num_cloud_servers
self.D = D
self.bandwidth = bandwidth
self.lambda_k_range = lambda_k_range
self.K_k_in_range = K_k_in_range
self.iot_devices = []
self.fog_devices = []
self.cloud_servers = []
self.create_devices()
self.create_fog_environment()
self.create_cloud_environment()
def create_devices(self):
np.random.seed(42)
for i in range(self.num_iot_devices):
computation_capacity = np.random.uniform(1, 5)
frequency = np.random.uniform(0.5, 2)
device = Device(i, computation_capacity, frequency)
self.iot_devices.append(device)
def create_fog_environment(self):
np.random.seed(43)
for i in range(self.num_fog_devices):
computation_capacity = np.random.uniform(5, 10)
frequency = np.random.uniform(2, 4)
fog_device = ExecutionEnvironment(i, computation_capacity, frequency, transmission_rate=10)
self.fog_devices.append(fog_device)
def create_cloud_environment(self):
np.random.seed(44)
for i in range(self.num_cloud_servers):
computation_capacity = np.random.uniform(10, 20)
frequency = np.random.uniform(4, 8)
cloud_server = ExecutionEnvironment(i, computation_capacity, frequency, transmission_rate=100)
self.cloud_servers.append(cloud_server)
def rco_task_offloading(tasks, cloud_devices):
execution_environments = []
total_energy = 0
total_delay = 0
def calculate_cloud_delay(task, cloud_devices):
cloud_device = random.choice(cloud_devices)
transmission_time = task['transmission_time'] / cloud_device.get_transmission_rate()
computation_time = task['required_cpu'] / cloud_device.get_computation_capacity()
return transmission_time + computation_time
def calculate_cloud_energy(task, cloud_devices):
cloud_device = random.choice(cloud_devices)
computation_time = task['required_cpu'] / cloud_device.get_computation_capacity()
return computation_time * 2.0
for index, task in tasks.iterrows():
execution_environments.append('Cloud')
total_energy += calculate_cloud_energy(task, cloud_devices)
total_delay += calculate_cloud_delay(task, cloud_devices)
return execution_environments, total_energy, total_delay
def pbco_task_offloading(tasks, fog_devices, cloud_devices):
execution_environments = []
total_energy = 0
total_delay = 0
def calculate_fog_delay(task, fog_devices):
fog_device = random.choice(fog_devices)
transmission_time = task['transmission_time'] / fog_device.get_transmission_rate()
computation_time = task['required_cpu'] / fog_device.get_computation_capacity()
return transmission_time + computation_time
def calculate_cloud_delay(task, cloud_devices):
cloud_device = random.choice(cloud_devices)
transmission_time = task['transmission_time'] / cloud_device.get_transmission_rate()
computation_time = task['required_cpu'] / cloud_device.get_computation_capacity()
return transmission_time + computation_time
def calculate_fog_energy(task, fog_devices):
fog_device = random.choice(fog_devices)
computation_time = task['required_cpu'] / fog_device.get_computation_capacity()
return computation_time * 1.0
def calculate_cloud_energy(task, cloud_devices):
cloud_device = random.choice(cloud_devices)
computation_time = task['required_cpu'] / cloud_device.get_computation_capacity()
return computation_time * 2.0
for index, task in tasks.iterrows():
offload_type = random.choices(['Fog', 'Cloud'], weights=[0.3, 0.7], k=1)[0] # 70% Cloud, 30% Fog
if offload_type == 'Fog':
execution_environments.append('Fog')
total_energy += calculate_fog_energy(task, fog_devices)
total_delay += calculate_fog_delay(task, fog_devices)
else:
execution_environments.append('Cloud')
total_energy += calculate_cloud_energy(task, cloud_devices)
total_delay += calculate_cloud_delay(task, cloud_devices)
return execution_environments, total_energy, total_delay
def task_offloading(tasks, model, iot_devices, fog_devices, cloud_devices):
execution_environments = []
total_energy = 0
total_delay = 0
def calculate_cloud_delay(task, cloud_devices):
cloud_device = min(cloud_devices, key=lambda c: c.get_computation_capacity())
transmission_time = task['transmission_time'] / cloud_device.get_transmission_rate()
computation_time = task['required_cpu'] / cloud_device.get_computation_capacity()
total_delay = transmission_time + computation_time
return total_delay
def calculate_fog_delay(task, fog_devices):
fog_device = min(fog_devices, key=lambda f: f.get_computation_capacity())
transmission_time = task['transmission_time'] / fog_device.get_transmission_rate()
computation_time = task['required_cpu'] / fog_device.get_computation_capacity()
total_delay = transmission_time + computation_time
return total_delay
def calculate_cloud_energy(task, cloud_devices):
cloud_device = min(cloud_devices, key=lambda c: c.get_computation_capacity()) # Select best cloud device
computation_time = task['required_cpu'] / cloud_device.get_computation_capacity()
energy_consumption = computation_time * 2.0 # Example coefficient for cloud energy
return energy_consumption
def calculate_fog_energy(task, fog_devices):
fog_device = min(fog_devices, key=lambda f: f.get_computation_capacity()) # Select best fog device
computation_time = task['required_cpu'] / fog_device.get_computation_capacity()
energy_consumption = computation_time * 1.0 # Example coefficient for fog energy
return energy_consumption
for index, task in tasks.iterrows():
task_type = None
device = next((dev for dev in iot_devices if dev.get_id() == task['device_id']), None)
if device and device.get_frequency() >= task['frequency']:
execution_environments.append('IIoT')
else:
task_features = task[['required_cpu', 'frequency', 'exec_deadline']].values.reshape(1, -1)
task_type = model.predict(task_features)[0]
if task_type == 1:
execution_environments.append('Fog')
total_energy += calculate_fog_energy(task, fog_devices)
total_delay += calculate_fog_delay(task, fog_devices)
else:
execution_environments.append('Cloud')
total_energy += calculate_cloud_energy(task, cloud_devices)
total_delay += calculate_cloud_delay(task, cloud_devices)
return execution_environments, total_energy, total_delay
# Create system and load model
iiot_system = IIoTSystem(20, 10, 3, 0.5, 50, [1, 5], [0.1, 1.0])
task_df = pd.read_csv('./source/data/iot_task_data_per_device.csv')
model = joblib.load('./source/models/logistic_regression_model.joblib')
# Execute task offloading
execution_environments, total_energy, total_delay = task_offloading(task_df, model, iiot_system.iot_devices, iiot_system.fog_devices, iiot_system.cloud_servers)
print(execution_environments)
print(total_energy)
print(total_delay)
rco_execution, rco_energy, rco_delay = rco_task_offloading(task_df, iiot_system.cloud_servers)
pbco_execution, pbco_energy, pbco_delay = pbco_task_offloading(task_df, iiot_system.fog_devices, iiot_system.cloud_servers)
ml_execution, ml_energy, ml_delay = task_offloading(task_df, model, iiot_system.iot_devices, iiot_system.fog_devices, iiot_system.cloud_servers)
# Use the extracted values for plotting
energy_values = [rco_energy, pbco_energy, ml_energy] # ML has the lowest energy
delay_values = [rco_delay, pbco_delay, ml_delay]
# Offloading strategies
strategies = ['ML-Based', 'RCO', 'PBCO']
# Energy consumption values
energy_values = [ml_energy, rco_energy, pbco_energy]
# Delay values
delay_values = [ml_delay, rco_delay, pbco_delay]
# Set bar width
bar_width = 0.4
x = np.arange(len(strategies))
# Create subplots for energy and delay
fig, ax = plt.subplots(1, 2, figsize=(12, 5))
colors = ['lightblue', 'lightcoral', 'lightgreen']
# Bar chart for Energy Consumption
ax[0].bar(x, energy_values, color=colors, width=bar_width)
ax[0].set_xticks(x)
ax[0].set_xticklabels(strategies)
ax[0].set_ylabel("Total Energy (J)")
ax[0].set_title("Energy Consumption Comparison")
ax[0].grid(axis='y', linestyle='--', alpha=0.7)
# Bar chart for Delay
ax[1].bar(x, delay_values, color=['blue', 'red', 'green'], width=bar_width)
ax[1].set_xticks(x)
ax[1].set_xticklabels(strategies)
ax[1].set_ylabel("Total Delay (s)")
ax[1].set_title("Delay Comparison")
ax[1].grid(axis='y', linestyle='--', alpha=0.7)
# Show the plot
plt.tight_layout()
plt.show()