计算卸载论文阅读01-理论梳理

news2024/11/26 2:44:30

标题:When Learning Joins Edge: Real-time Proportional Computation Offloading via Deep Reinforcement Learning

会议:ICPADS 2019

一、梳理

问题:在任务进行卸载时,往往忽略了任务的特定的卸载比例。

模型:针对上述问题,我们提出了一种创新的强化学习(RL)方法来解决比例计算问题。我们考虑了一种常见的卸载场景,该场景具有时变带宽和异构设备,并且设备不断生成应用程序。对于每个应用程序,客户端必须选择本地或远程执行该应用程序,并确定要卸载的比例。我们将该问题制定为一个长期优化问题,然后提出一种基于RL的算法来解决该问题。基本思想是估计可能决策的收益,其中选择收益最大的决策。我们没有采用原来的深度Q网络(DQN),而是通过添加优先级缓冲机制专家缓冲机制,提出了Advanced DQN(ADQN),分别提高了样本的利用率和克服了冷启动问题。

目的:最小化时延和能耗的权值和(优化参数:用户卸载策略卸载的比例)。

算法:ADQN。

二、模型细节与算法

2.1系统模型

计算卸载主要包含: 本地计算和边缘计算

1、本地计算:用户U_i在时隙t_j时的计算时延(计算时延和排队时延)和能耗为

T_{ij}^{l}=D_{ij}^{l}+t_{q}^{l}=\frac{\omega B_{ij}Q_{y_{ij}}}{f_{ij}^{l}}+t_{q}^{l}

E_{ij}^{l}=e_lB_{ij}Q_{y_{ij}}

其中B_{ij}表示任务大小,Q_{y_{ij}}表示本地计算任务的比例

2、边缘计算:包含时延(上下行传输时延+执行时延+排队时延)和能耗
T_{ij}^{r}=D_{ij}^{r}+t_q^r=\frac{\omega B_{ij}P_{y_{ij}}}{F_{ij}^r}+\frac{B_{ij}P_{y_{ij}}}{r_{ul}^{ij}}+\frac{\omega^s B_{ij}}{r_{dl}^{ij}} + t_q^r

E_{ij}^r=e_r B_{ij}P_{y_{ij}}

其中P_{y_{ij}}表示卸载到边缘服务器的比例,\omega^s表示每单位计算任务处理后得到的结果大小。

3、总的时延与能耗成本

W_{ij}=\lambda \max (T_{ij}^r,T_{ij}^l)+\beta(E_{ij}^r+E_{ij}^l)

2.2优化目标

\min \sum_{t_j=1}^{T}[W_{ij}]

       {\tt s.t.}   f_{x_{ij}}^r \leqslant F_{x_{ij}}^r, f_{x_{ij}}^l \leqslant F_{x_{ij}}^l

                r_{ul}^{ij} \leqslant R_{ul}^i, r_{dl}^{ij} \leqslant R_{dl}^i

                x_{ij} \in {1,2,...,m},y_{ij} \in {1,2,...,n}

2.3 State、Action和Reward

1、状态空间:

状态空间包含:(数据大小、本地CPU频率,local可用计算资源,上行速率,下行速率,ES可用计算资源)

2、动作空间:

动作空间包含:(用户选择ES的策略,任务卸载比例)

3、奖励:

奖励:R=\frac{W_l - W(s,a)}{W_l}

W_l表示本地计算成本,W(s,a)表示部分卸载产生的成本。

2.4代码

计算卸载环境代码:

import math
import copy
import numpy as np


class ENV():
    def __init__(self, UEs=3, MECs=7, k=33, lam=0.5):
        self.UEs = UEs
        self.MECs = MECs
        self.k = k

        q = np.full((k, 1), 0.)
        p = np.linspace(0, 1, k).reshape((k, 1))
        # Create Action
        for i in range(MECs - 1):
            a = np.full((k, 1), float(i + 1))
            b = np.linspace(0, 1, k).reshape((k, 1))
            q = np.append(q, a, axis=0)
            p = np.append(p, b, axis=0)  # 231(33 * 7) * 33

        self.actions = np.hstack((q, p))  # 231 * 2
        self.n_actions = len(self.actions)  # 231
        self.n_features = 3 + MECs * 3  # 3 + 7 * 3
        self.discount = 0.01

        # 基本参数
        # 频率
        self.Hz = 1
        self.kHz = 1000 * self.Hz
        self.mHz = 1000 * self.kHz
        self.GHz = 1000 * self.mHz
        self.nor = 10 ** (-7)
        self.nor1 = 10 ** 19

        # 数据大小
        self.bit = 1
        self.B = 8 * self.bit
        self.KB = 1024 * self.B
        self.MB = 1024 * self.KB

        # self.task_cpu_cycle = np.random.randint(2 * 10**9, 3* 10**9)

        self.UE_f = np.random.randint(1.5 * self.GHz * self.nor, 2 * self.GHz * self.nor)  # UE的计算能力
        self.MEC_f = np.random.randint(5 * self.GHz * self.nor, 7 * self.GHz * self.nor)  # MEC的计算能力
        # self.UE_f = 500 * self.mHz     # UE的计算能力
        # self.MEC_f = np.random.randint(5.2 * self.GHz, 24.3 * self.GHz)  # MEC的计算能力
        self.tr_energy = 1  # 传输能耗
        self.r = 40 * math.log2(1 + (16 * 10)) * self.MB * self.nor  # 传输速率
        # self.r = 800 # 传输速率
        self.ew, self.lw = 10 ** (-26), 3 * 10 ** (-26)  # 能耗系数
        # self.ew, self.lw = 0.3, 0.15 # 能耗系数
        self.et, self.lt = 1, 1
        self.local_core_max, self.local_core_min = 1.3 * self.UE_f, 0.7 * self.UE_f
        self.server_core_max, self.server_core_min = 1.3 * self.MEC_f, 0.7 * self.MEC_f
        self.uplink_max, self.uplink_min = 1.3 * self.r, 0.7 * self.r
        self.downlink_max, self.downlink_min = 1.3 * self.r, 0.7 * self.r
        self.lam = lam
        self.e = 1

    def reset(self):
        # 初始化环境,状态空间
        obs = []
        servers_cap = []
        new_cap = True
        for i in range(self.UEs):
            uplink, downlink = [], []
            # np.random.seed(np.random.randint(1, 1000))
            # task_size = np.random.randint(2 * 10**8 * self.nor, 3 * 10**8 * self.nor) #   任务大小
            task_size = np.random.randint(1.5 * self.mHz, 2 * self.mHz)  # 任务大小
            # self.task_size = self.task_size * self.task_cpu_cycle                     # 处理一个任务所需要的cpu频率
            # task_cpu_cycle = np.random.randint(2 * 10**9 * self.nor, 3 * 10**9 * self.nor)
            task_cpu_cycle = np.random.randint(10 ** 3, 10 ** 5)
            local_comp = np.random.randint(0.9 * self.UE_f, 1.1 * self.UE_f)  # UE的计算能力
            for i in range(self.MECs):
                up = np.random.randint(0.9 * self.r, 1.1 * self.r)
                down = np.random.randint(0.9 * self.r, 1.1 * self.r)
                if new_cap:
                    cap = np.random.randint(0.9 * self.MEC_f, 1.1 * self.MEC_f)  # MEC计算能力
                    servers_cap.append(cap)
                uplink.append(up)
                downlink.append(down)
            observation = np.array([task_size, task_cpu_cycle, local_comp])
            observation = np.hstack((observation, servers_cap, uplink, downlink))
            obs.append(observation)
            new_cap = False
        return obs

    def choose_action(self, prob):
        """
        根据概率选择动作
        :param prob:
        :return:
        """
        action_choice = np.linspace(0, 1, self.k)
        actions = []
        for i in range(self.UEs):
            a = np.random.choice(a=(self.MECs * self.k), p=prob[i])
            target_server = int(a / self.k)
            percen = action_choice[a % self.k]
            action = [target_server, percen]
            actions.append(action)
        return actions

    def step(self, observation, actions_prob, is_prob=True, is_compared=True):
        if is_prob:
            actions = self.choose_action(actions_prob)
        else:
            actions = actions_prob
        new_cap = False
        obs_ = []
        rew, local, ran, mec = [], [], [], []
        dpg_times, local_times, ran_times, mec_times = [], [], [], []
        dpg_energys, local_energys, ran_energys, mec_energys = [], [], [], []
        total = []
        a, b, c, d = 0, 0, 0, 0
        for i in range(self.UEs):
            if i == self.UEs - 1:
                new_cap = True
            # 提取信息
            task_size, task_cpu_cycle, local_comp, servers_cap, uplink, downlink = \
                observation[i][0], observation[i][1], observation[i][2], observation[i][3:3+self.MECs], observation[i][3+self.MECs:3+self.MECs*2], observation[i][3+self.MECs*2:3+self.MECs*3]

            action = actions[i]
            target_server, percen = int(action[0]), action[1]

            # 计算奖励
            # 1=======部分卸载==========
            # 卸载及回传数据产生的时延和能耗
            tr_time = (percen * task_size) / uplink[target_server] + self.discount * (percen * task_size) / downlink[
                target_server]
            tr_energy = (self.tr_energy * percen * task_size) / uplink[target_server] + self.discount * (
                        self.tr_energy * percen * task_size) / downlink[target_server]

            # 本地计算时延和能耗
            comp_local_time = task_cpu_cycle * (1 - percen) / (local_comp)
            comp_local_energy = self.lw * task_cpu_cycle * (1 - percen) * local_comp ** 2

            # 边缘计算时延和能耗
            comp_mec_time = (percen * task_cpu_cycle) / servers_cap[target_server]
            comp_mec_energy = self.ew * percen * task_cpu_cycle * servers_cap[target_server] ** 2

            # 最大计算时延
            comp_time = max(comp_local_time, comp_mec_time)
            time_cost = (comp_time + tr_time) * self.et
            # 能耗成本
            energy_cost = (tr_energy + comp_local_energy + comp_mec_energy) * self.e
            # 总成本
            total_cost = self.lam * time_cost + (1 - self.lam) * energy_cost

            # 2、=======完全本地计算==========
            local_only_time = task_cpu_cycle / (local_comp) * self.et
            local_only_energy = self.lw * task_cpu_cycle * local_comp ** 2 * self.e
            # local_only_energy = task_size * local_comp
            local_only = self.lam * local_only_time + (1 - self.lam) * local_only_energy

            # 3、=======完全边缘计算==========
            mec_only_tr_time = task_size / uplink[target_server] + self.discount * task_size / downlink[target_server]
            mec_only_tr_energy = self.tr_energy * task_size / uplink[
                target_server] + self.discount * self.tr_energy * task_size / downlink[target_server]
            # print("mec_only_tr_time:", mec_only_tr_time)
            # print("mec_only_tr_energy:", mec_only_tr_energy)

            mec_only_comp_time = task_cpu_cycle / servers_cap[target_server]
            mec_only_comp_energy = self.ew * task_cpu_cycle * servers_cap[target_server] ** 2
            # mec_only_comp_energy = task_size * servers_cap[target_server]
            # print("mec_only_comp_time:", mec_only_comp_time)
            # print("mec_only_comp_energy:", mec_only_comp_energy)

            mec_only_time_cost = (mec_only_tr_time + mec_only_comp_time) * self.et
            mec_only_energy_cost = (mec_only_tr_energy + mec_only_comp_energy) * self.e

            mec_only = self.lam * mec_only_time_cost + (1 - self.lam) * mec_only_energy_cost

            # 4、=======随机卸载==========
            percen_ran = np.random.uniform()  # 随机卸载比例
            mec_ran = np.random.randint(self.MECs)  # 随机选择一个服务器进行卸载

            random_tr_time = (percen_ran * task_size) / uplink[mec_ran] + (self.discount * percen_ran * task_size) / \
                             downlink[mec_ran]
            random_tr_energy = (self.tr_energy * percen_ran * task_size) / uplink[mec_ran] + self.discount * (
                        self.tr_energy * percen_ran * task_size) / downlink[mec_ran]

            random_comp_local_time = (1 - percen_ran) * task_cpu_cycle / local_comp
            random_comp_local_energy = self.lw * (1 - percen_ran) * task_cpu_cycle * local_comp ** 2
            # random_comp_local_energy = (1 - percen_ran) * task_size * local_comp

            random_comp_mec_time = percen_ran * task_cpu_cycle / servers_cap[mec_ran]
            random_comp_mec_energy = self.ew * percen_ran * task_cpu_cycle * servers_cap[mec_ran] ** 2
            # random_comp_mec_energy = percen_ran * task_size * servers_cap[mec_ran]

            random_comp_time = max(random_comp_local_time, random_comp_mec_time)
            random_time_cost = (random_comp_time + random_tr_time) * self.et
            random_energy_cost = (random_tr_energy + random_comp_local_energy + random_comp_mec_energy) * self.e

            random_total = self.lam * random_time_cost + (1 - self.lam) * random_energy_cost
            random_total_cost2 = random_energy_cost

            reward = -total_cost

            # 得到下一个observation
            x = np.random.uniform()
            y = 0.5
            if x > y:
                local_comp = min(local_comp + np.random.randint(0, 0.2 * self.UE_f), self.local_core_max)
                for j in range(self.MECs):
                    cap = min(servers_cap[j] + np.random.randint(0, 0.3 * self.UE_f), self.server_core_max)
                    # MEC容量保持一致
                    if new_cap:
                        for x in range(self.UEs):
                            observation[x][2 + j] = cap
                    downlink[j] = min(downlink[j] + np.random.randint(0, 0.2 * self.r), self.downlink_max)
                    uplink[j] = min(uplink[j] + np.random.randint(0, 0.2 * self.r), self.uplink_max)
            else:
                local_comp = max(local_comp + np.random.randint(-0.2 * self.UE_f, 0), self.local_core_min)
                for j in range(self.MECs):
                    # MEC容量保持一致
                    if new_cap:
                        cap = max(servers_cap[j] + np.random.randint(0, 0.3 * self.UE_f), self.server_core_max)
                        for x in range(self.UEs):
                            observation[x][2 + j] = cap
                    downlink[j] = max(downlink[j] - np.random.randint(0, 0.2 * self.r), self.downlink_min)
                    uplink[j] = max(uplink[j] - np.random.randint(0, 0.2 * self.r), self.uplink_min)

            task_size = np.random.randint(10, 50)
            task_cpu_cycle = np.random.randint(10 ** 3, 10 ** 5)  # 处理任务所需要的CPU频率
            observation_ = np.array([task_size, task_cpu_cycle, local_comp])
            observation_ = np.hstack((observation_, servers_cap, uplink, downlink))
            obs_.append(observation_)

            rew.append(reward)
            local.append(local_only)
            mec.append(mec_only)
            ran.append(random_total)

            dpg_times.append(time_cost)
            local_times.append(local_only_time)
            mec_times.append(mec_only_time_cost)
            ran_times.append(random_time_cost)

            dpg_energys.append(energy_cost)
            local_energys.append(local_only_energy)
            mec_energys.append(mec_only_energy_cost)
            ran_energys.append(random_energy_cost)

            total.append(total_cost)

        if is_compared:
            return obs_, rew, local, mec, ran, dpg_times, local_times, mec_times, ran_times, dpg_energys, local_energys, mec_energys, ran_energys, total
        else:
            return obs_, rew, dpg_times, dpg_energys

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/477962.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BUUCTF ciscn_2019_c_1

小白垃圾做题笔记而已,不建议阅读。 1前期: 其实刚开始拿到程序的时候我还以为是逆向题放错地方了。唉,做题太少了。啥也不会。我是大笨蛋。 题目中用的是ubuntu18,我的ubuntu没怎么用过,vmtools都不能用&#xff0c…

【源码解析】canal核心功能源码解析

1. 项目地址 https://github.com/alibaba/canal.git2. 模块介绍 canal核心模块的功能: deployer模块:独立部署模块,用于canal-server的独立启动,包括本地配置解析、拉取远程配置、启动canal-server。server模块:cana…

山东专升本计算机第六章-数据库技术

数据库技术 SQL数据库与NOSQL数据库的区别 数据库管理系统 考点 6 数据库管理系统的组成和功能 组成 • 模式翻译 • 应用程序的翻译 • 交互式查询 • 数据的组织和存取 • 事务运行管理 • 数据库的维护 功能 • 数据定义功能 • 数据存取功能 • 数据库运行管理…

MySQL备份和恢复

文章目录 一、库的备份和恢复1.库的备份2.库的恢复 二、表的备份和恢复1.表的备份2.表的恢复 备份数据,其实就是生成一个 sql 文件,把创建数据库、创建表、插入数据等各种 SQL 语句都装载到这个文件中。恢复数据,其实就是按顺序执行 sql 文件…

操作系统进程概述、通信

进程 进程就是程序的一次执行过程,同一个程序多次执行对应多个进程; 一、进程的组成 1、PCB (1)进程描述信息:主要是PID等关键信息; (2)进程控制和管理信息; &#xf…

( 数组和矩阵) 566. 重塑矩阵 ——【Leetcode每日一题】

❓566. 重塑矩阵 难度:简单 在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。 给你一个由二维数组 mat 表示的 m x n 矩阵…

unity-VRTK-simulator开发学习日记3(射线样式|忽略层|有无效名单)

目录 射线样式 组成 可用状态 材质替换 射线激活设置为常态 忽略层级(射线等) 自定义忽略层级 (射线等) 有效名单和无效名单 有效名单 无效名单 创建一个模拟手柄的按钮(键盘键入按钮) 输入系统…

最新Wordpress网站因重装宝塔而导致数据库崩溃无法访问的终极解决办法

在当今数字化时代,拥有自己的网站已成为越来越多人展示个人或企业信息的重要方式。虽然建立并维护自己网站看起来是一个简单的过程,但如果出现问题,比如数据丢失、网站无法正常运行等情况时,往往会令用户感到十分懊恼和无助。在这…

sql注入(二)盲注,二次注入,宽字节注入

目录 目录 一、布尔盲注 1.判断库名的长度 2.判断数据库名 2.1判断数据库名首字符 2.2 判断数据库名的其余字符 二、时间盲注: 1.判断库名的长度 2.判断库名: 3.判断表名payload: 4.爆出列名 5.爆数据 三、二次注入 1.原理&#…

【某软件网络协议分析】

由于网站无法上传附件,本帖子完整内容请点击此处 首先,从coco.apk提取dex文件,利用dex2jar将dex转化为jar,拖到jd-gui中,发现有如下几个可疑点: com.azus.android.tcplogin.CryptUtil.rsaEncrypt com.azus…

MySQL示例数据库(MySQL Sample Databases) 之 Employees 数据库

文章目录 MySQL示例数据库(MySQL Sample Databases) 之 Employees 数据库官方示例数据介绍Employees 数据库Employees 数据库安装Employees 数据库的结构参考 MySQL示例数据库(MySQL Sample Databases) 之 Employees 数据库 官方示例数据介绍 MySQL 官方提供了多个示例数据库…

二叉树及其遍历

文章目录 二叉树树的定义二叉树的定义遍历先序遍历中序遍历后序遍历层次遍历定义队列层次创建二叉树层次遍历 二叉树 树是一种非线性的数据结构,由若干个节点组成,节点之间存在一种父子关系,具有层次结构。二叉树是一种特殊的树结构&#xff…

火遍全网的ChatGPT究竟是什么?

ChatGPT是什么 ChatGPT是一个由OpenAI开发的大型语言模型,基于GPT-3.5架构。它被训练用于自然语言处理和生成任务,可以回答各种问题,包括一般知识、文化、科学、技术、商业、娱乐等方面的问题。ChatGPT可以进行对话,回答用户的问…

OJ刷题 第十四篇(递归较多)

23204 - 进制转换 时间限制 : 1 秒 内存限制 : 128 MB 将一个10进制数x(1 < x < 100,000,000)转换成m进制数(2< m < 16) 。分别用 ABCDEF表示10以上的数字。 输入 x m (1 < x < 100,000,000, 2< m < 16) 输出 m进制数 样例 输入 31 16 输出 1F 答…

功能齐全的 ESP32 智能手表,具有多个表盘、心率传感器硬件设计

相关设计资料下载ESP32 智能手表带心率、指南针设计资料(包含Arduino源码+原理图+Gerber+3D文件).zip 介绍 我们调查了智能手表项目的不同方面,并学会了集成和测试每个单独的部分。在本文中,我们将使用所学知识,结合使用硬件和软件组件,从头开始创建我们自己的智能手表。在…

存储资源调优技术——SmartDedupe智能数据重删、SmartCompression智能数据压缩技术

目录 SmartDedupe智能数据重删技术 SmartCompression智能数据压缩技术 SmartDedupe智能数据重删技术 基本概念 智能数据重删技术 是一种数据缩减技术&#xff0c;通过删除存储系统中的冗余数据块 减少数据占用的物理存储容量&#xff0c;节省存储空间&#xff08;会降低性能&a…

Java 基础入门篇(三)——— 数组的定义与内存原理

文章目录 一、数组的定义1.1 静态初始化数组1.2 动态初始化数组1.3 数组的访问 二、数组的遍历三、数组的内存图 ★3.1 Java 的内存分配3.2 数组的内存图3.3 两个数组变量指向同一个数组对象 四、数组使用的常见问题补充&#xff1a;随机数 Random 类 一、数组的定义 数组就是…

线程池~~

文章目录 线程池线程池实现API、参数说明线程池处理Runnable任务线程池处理Callable任务Executors工具类实现线程池定时器Timer定时器ScheduledExecutorService定时器 并发和并行线程的生命周期 线程池 线程池实现API、参数说明 线程池处理Runnable任务 线程池处理Callable任务…

Win11的两个实用技巧系列之修改c盘大小方法、功能快捷键大全

Win11 c盘无法更改大小什么原因?Win11修改c盘大小方法 有不少朋友反应Win11 c盘无法更改大小是怎么回事&#xff1f;本文就为大家带来了详细的更改方法&#xff0c;需要的朋友一起看看吧 Win11 c卷无法更改大小什么原因&#xff1f;有用户电脑的系统盘空间太小了&#xff0c;…

CTF权威指南 笔记 -第二章二进制文件-汇编原理

C语言的生命是从 源文件开始 的 每条C语言都必须要给翻译成 一系列的低级语言 最后 按照可执行文件格式打包 并且作为二进制文件保存起来 编译原理 我们需要使用编译器 是通过某种语言 等价输出另一个语言 可以分为前端和后端 前端 和机器无关 把源程序分解为组成要素 …