【BES2500x系列 -- RTX5操作系统】Battery模块 -- 邮箱线程诞生的第一视角 -- osThreadDef --(十三)

news2024/9/22 8:34:47

请添加图片描述

  • 💌 所属专栏:【BES2500x系列】

  • 😀 作  者:我是夜阑的狗🐶

  • 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询!

  • 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘

您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!🤩 🤩 🤩

请添加图片描述

文章目录

  • 前言
  • 1 系统初始化
      • 1.1 邮箱线程的诞生
      • 1.2 app_os_init()
  • 2 Battery模块
      • 2.1 app_mailbox_init()
      • 2.2 osMailQDef()
      • 2.3 osMailQ()
      • 2.4 osThreadDef
      • 2.5 app_thread()
      • 2.6 osThread
  • 总结


<<【系列文章索引】>>

前言

  大家好,又见面了,我是夜阑的狗🐶,本文是专栏【BES2500x系列】专栏的第13篇文章;
  今天开始学习BES2500x系列的一天💖💖💖,开启新的征程,记录最美好的时刻🎉,每天进步一点点。
  专栏地址:【BES2500x系列】, 此专栏是我是夜阑的狗对BES2500x系列开发过程的总结,希望能够加深自己的印象,以及帮助到其他的小伙伴😉😉。对了,前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。
  如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。


1 系统初始化

  前面学习了嵌入式系统启动的基本流程,可以分为 引导程序 和 系统初始化程序 这两部分,并了解系统初始化中各个函数作用,但是看到这里我们估计还是一头雾水,此时就有大佬说“不妨从 Battery 模块入手了解该 SDK 框架”。那接下来就学习 Battery 模块具体是怎么跑的吧。话不多说,让我们原文再续,书接上回吧。

请添加图片描述

1.1 邮箱线程的诞生

  从上一篇文章可以了解到系统的 main 函数是如何跑到的,并且在讲解 main 函数中各个函数的作用,还知道了 main 中的 app_init 应用初始化涉及到了蓝牙、存储、系统状态、电源管理以及音频等方面的初始化和配置。知道这些初始化流程之后,接下来就深入了解一下 Battery 模块是怎么运转的吧,可以在 app.cpp 文件中看到该 app_init 函数。

在这里插入图片描述

  这里由于 app_init 函数代码过多,这里不就放出来了,只讲解一下其中的各个函数作用。app_init 函数中 个别函数 讲解

1.2 app_os_init()

  这段代码是一个应用程序操作系统初始化函数的实现,我们可以看到了线程创建,这是 CMSIS 的风格,相信开发过 STM32 的大佬应该比较熟悉,用来定义线程、定时器和邮箱通讯等。

  • 代码
/**
 * 初始化操作系统环境
 * 
 * 该函数负责初始化应用程序的操作系统环境它首先尝试初始化邮箱,然后创建一个应用线程
 * 这是应用程序启动的入口点,确保操作系统环境正确初始化,以便应用程序能够正常运行
 * 
 * @return 返回-1表示初始化失败,0表示成功
 */
int app_os_init(void)
{
    // 初始化邮箱系统,如果失败则返回-1
    if (app_mailbox_init())
        return -1;

    // 创建应用线程,如果创建失败则返回0
    app_thread_tid = osThreadCreate(osThread(app_thread), NULL);
    if (app_thread_tid == NULL)  {
        TRACE(0,"Failed to Create app_thread\n");
        return 0;
    }
    return 0;
}
  • 参数/函数讲解
序号参数/函数说明
1app_mailbox_init()初始化应用程序的邮箱,邮箱通常用于线程间的通信和消息传递。如果初始化失败,函数会返回非零值。
2osThreadCreate()创建了一个名为 app_thread 的线程,并将其标识符保存在 app_thread_tid 变量中。osThreadCreate 是操作系统提供的函数,用于创建一个新的线程。osThread 宏用于指定要创建的线程的名称。

2 Battery模块

  在系统初始化中,我们可以看到调用邮箱线程初始化函数,接下来看看里面都做了些什么吧

2.1 app_mailbox_init()

  • 代码
/**
 * 初始化应用程序邮箱
 * 
 * 本函数用于创建一个邮箱对象,并初始化相关计数器。如果创建失败,则会打印错误信息并返回负值。
 * 
 * @param 无
 * @return int 返回0表示成功,返回-1表示失败。
 */
static int app_mailbox_init(void)
{
    // 创建邮箱对象,如果创建失败,则返回-1
    app_mailbox = osMailCreate(osMailQ(app_mailbox), NULL);
    if (app_mailbox == NULL)  {
        TRACE(0,"Failed to Create app_mailbox\n");
        return -1;
    }

    // 初始化邮箱使用计数器
    app_mailbox_cnt = 0;
    return 0;
}

  本函数用于创建一个邮箱对象,并初始化相关计数器。如果创建失败,则会打印错误信息并返回负

  • 参数/函数讲解
序号参数/函数说明
1osMailCreate创建邮箱队列
2osMailQ该宏通过指定的邮箱队列名称,生成一个指向该邮箱队列定义的指针。

2.2 osMailQDef()

  一般在文件开头会看到这样的定义:osMailQDef

  • 代码
/**
 * 定义一个邮箱队列。
 * 
 * 该函数用于定义一个邮箱队列,邮箱队列名为app_mailbox,最大容量为APP_MAILBOX_MAX,消息块类型为APP_MESSAGE_BLOCK。
 * 这是一个静态邮箱队列定义,意味着它在程序运行期间一直存在。
 * 
 * @param app_mailbox 邮箱队列的名称。
 * @param APP_MAILBOX_MAX 邮箱队列的最大容量。
 * @param APP_MESSAGE_BLOCK 消息块的类型。
 */
osMailQDef (app_mailbox, APP_MAILBOX_MAX, APP_MESSAGE_BLOCK);

// 静态邮箱队列的ID初始化为NULL。
static osMailQId app_mailbox = NULL;

  该函数用于定义一个邮箱队列,邮箱队列名为 app_mailbox,最大容量为APP_MAILBOX_MAX,消息块类型为 APP_MESSAGE_BLOCK。这是一个静态邮箱队列定义,意味着它在程序运行期间一直存在。这个邮箱队列可以用于多线程或任务之间的数据通信,确保数据安全地传递。app_mailbox 是一个全局变量,用于存储邮箱队列的标识符,方便后续操作。

/**
 * 定义一个邮箱队列。
 * 
 * 该宏用于静态定义一个邮箱队列以及相关配置,以便在系统运行时使用。邮箱队列可以用来在任务之间传递消息。
 * 
 * @param name 邮箱队列的名称。
 * @param queue_sz 邮箱队列中邮件的最大数量。
 * @param type 邮件中数据的类型。
 * 
 * @note 此宏定义了一个静态数组来存储邮件,以及一个osMailQDef_t类型的结构体来描述邮箱队列。
 */
#define osMailQDef(name, queue_sz, type) \
static uint32_t os_mailQ_m_##name[3+((sizeof(type)+3)/4)*(queue_sz)]; \
osMailQDef_t os_mailQ_def_##name = \
{ {(queue_sz), sizeof(type), (os_mailQ_m_##name)}, NULL, {NULL} }
  • 参数/函数讲解

  该C语言宏 osMailQDef 用于在 FreeRTOS 操作系统中创建和初始化一个邮箱(Mail Queue)结构体。具体功能如下:
  1、定义内存缓冲区:首先,它创建一个名为 os_mailQ_m_name 的静态 uint32_t 类型的数组。数组的大小基于参数 queue_sz (队列容量)和 type (邮件的数据类型)计算得出。计算方式是 (sizeof(type) + 3) / 4,确保数组大小能完整容纳任何type类型的对象,并且对4字节对齐。
  2、初始化MailQ结构体:然后,它定义了一个 osMailQDef_t 类型的变量os_mailQ_def_name。该结构体包含以下字段:

序号参数/函数说明
1mailQ队列的大小(元素个数),由 queue_sz 提供。
2mailSize单个邮件的大小,由 sizeof(type) 提供,用于确保正确分配和传递邮件数据。
3pool指向上面定义的内存缓冲区的指针,即os_mailQ_m_name
4list和mutex这两个字段通常与 FreeRTOS 的内部管理有关,用于同步和保护邮箱操作,这里它们被初始化为NULL

  通过这个宏,用户可以在编译时创建邮箱队列,为实时操作系统中的任务间安全通信提供支持。

2.3 osMailQ()

  • 代码
/**
 * 宏定义用于获取指定名称的邮箱队列的地址。
 * 
 * 该宏通过指定的邮箱队列名称,生成一个指向该邮箱队列定义的指针。
 * 
 * @param name 邮箱队列的名称。此参数将被直接用于构建邮箱队列指针的名称。
 * @return 返回一个指向指定名称的邮箱队列定义的指针。
 */
#define osMailQ(name) \
&os_mailQ_def_##name
  • 参数/函数讲解
序号参数/函数说明
1osMailQ该宏通过指定的邮箱队列名称,生成一个指向该邮箱队列定义的指针。

2.4 osThreadDef

  接下来就让我们来深入看下 osThreadCreate(osThread(app_thread), NULL) 是怎么跑的吧。一般在文件开头会看到这样的定义:osThreadDef

  • 代码
static void app_thread(void const *argument);
osThreadDef(app_thread, osPriorityHigh, 1, APP_THREAD_STACK_SIZE, "app_thread");

  定义了一个名为 app_thread 的线程,具有高优先级 osPriorityHigh,只有一个实例,栈大小为 APP_THREAD_STACK_SIZE,线程的任务名称为 “app_thread”。

/*
 * 定义一个操作系统的线程定义。
 * 
 * 参数:
 * name: 线程名称的前缀。
 * priority: 线程的优先级。
 * instances: 线程实例的数量。如果为1,则创建一个静态实例;否则,创建动态实例。
 * stacksz: 线程栈的大小(字节)。如果为0,则分配最小栈大小。
 * task_name: FreeRTOS任务的名称。
 * 
 * 返回值:无。
 * 
 * 说明:此宏用于预先定义线程的栈、控制块和FreeRTOS线程定义结构体。
 */
#define osThreadDef(name, priority, instances, stacksz, task_name) \
static uint64_t os_thread_stack##name[(stacksz)?(((stacksz+7)/8)):1]; \
static StaticTask_t os_thread_cb_##name; \
const osThreadDef_t os_thread_def_##name = \
{ (name), \
  { task_name, osThreadDetached, \
    (instances == 1) ? (&os_thread_cb_##name) : NULL,\
    (instances == 1) ? sizeof(StaticTask_t) : 0U, \
    ((stacksz) && (instances == 1)) ? (&os_thread_stack##name) : NULL, \
    8*((stacksz+7)/8), \
    (priority), 0U, 0U } }
  • 参数/函数讲解

  这是一个宏定义,用于定义线程的属性。它包括了以下几个部分:

序号参数/函数说明
1os_thread_stack##name[(stacksz)?(((stacksz+7)/8)):1]这行代码定义了一个名为 os_thread_stack<name> 的静态数组,用于存储线程的堆栈。堆栈的大小由 stacksz 决定,通过 (stacksz+7)/8 计算出需要的 uint64_t 类型的元素个数,并且使用三元运算符 (stacksz)?(((stacksz+7)/8)):1 确保至少有一个元素。
2static StaticTask_t os_thread_cb_##name这行代码定义了一个名为 os_thread_cb_<name> 的静态变量,用于存储线程控制块。
3const osThreadDef_t os_thread_def_##name这行代码定义了一个名为 os_thread_def_<name> 的常量,类型为 osThreadDef_t,其中包含了线程的名称、任务名称、控制块、堆栈等属性。

  宏定义中的最后一部分是一个结构体的初始化,具体属性如下:

序号参数/函数说明
1(name)线程名称。
2{ task_name, osThreadDetached, … }任务的属性,包括任务名称和任务的状态(这里是 osThreadDetached,表示线程是一个分离线程)。
3(instances == 1) ? (&os_thread_cb_##name) : NULL如果线程只有一个实例,将指向线程控制块的指针赋给 cb_mem,否则为 NULL
4(instances == 1) ? sizeof(StaticTask_t) : 0U如果线程只有一个实例,将线程控制块的大小赋给 cb_size,否则为 0U。
5((stacksz) && (instances == 1)) ? (&os_thread_stack##name) : NULL如果线程有堆栈且只有一个实例,将指向堆栈的指针赋给 stack_mem,否则为 NULL
68*((stacksz+7)/8)堆栈的大小,保证是 uint64_t 类型的整数倍。
7(priority)线程的优先级

  总的来说,这段代码定义了一个线程及其相关的属性,包括线程名称、任务名称、线程控制块、堆栈等。

/// Thread Definition structure contains startup information of a thread.
#if (osCMSIS < 0x20000U)
typedef struct os_thread_def {
  os_pthread                 pthread;   ///< start address of thread function
  osPriority               tpriority;   ///< initial thread priority
  uint32_t                 instances;   ///< maximum number of instances of that thread function
  uint32_t                 stacksize;   ///< stack size requirements in bytes; 0 is default stack size
} osThreadDef_t;
#else
typedef struct os_thread_def {
  os_pthread                 pthread;   ///< start address of thread function
  osThreadAttr_t                attr;   ///< thread attributes
} osThreadDef_t;
#endif

  从前面线程赋值来看,这里用的第二个结构体, osThreadDef宏就是给该结构体变量初始化赋值。

2.5 app_thread()

  • 代码
static void app_thread(void const *argument)
{
    while(1){
        APP_MESSAGE_BLOCK *msg_p = NULL; // 声明了一个指向 APP_MESSAGE_BLOCK 类型的指针 msg_p,并将其初始化为 NULL。

        if (!app_mailbox_get(&msg_p)) { // 从邮箱中获取消息,并将消息的指针存储在 msg_p 中
            if (msg_p->mod_id < APP_MODUAL_NUM) {
                if (mod_handler[msg_p->mod_id]) { //检查模块处理函数是否存在。如果模块处理函数存在,则进入条件语句中执行后续操作。
                    int ret = mod_handler[msg_p->mod_id](&(msg_p->msg_body)); // 调用了模块处理函数,并将消息体作为参数传递给它。
                    if (ret)
                        TRACE(2,"mod_handler[%d] ret=%d", msg_p->mod_id, ret);
                }
            }
            app_mailbox_free(msg_p); // 释放了消息所占用的内存,防止内存泄漏。
        }
    }
}
  • 参数/函数讲解
序号参数/函数说明
1app_mailbox_get()从邮箱中获取消息,并将消息的指针存储在 msg_p 中
2app_mailbox_free()释放了消息所占用的内存,防止内存泄漏
3mod_handler[]各模块钩子注册的数组

  总的来说,这段代码表示一个线程不断地从邮箱中获取消息,并根据消息中的模块 ID 找到对应的模块处理函数进行处理,然后释放消息所占用的内存。

2.6 osThread

  • 代码
/// Access a Thread definition.
/// \param         name          name of the thread definition object.
#define osThread(name) \
&os_thread_def_##name
  • 参数/函数讲解

  这个宏定义简单地返回了指向特定线程定义结构体的指针。具体来说,它会返回一个指针,该指针指向了以 os_thread_def_<name> 命名的线程定义结构体。通过上面一系列的说明可以知道,该 os_thread_def_<name> 结构体已经被初始化好了,所以是可以获取的。这个宏可以在代码中使用,以便获取特定线程的定义结构体指针,然后可以在操作系统中使用这个指针来管理和操作该线程。

<<【系列文章索引】>>

请添加图片描述


总结

  前面大费周章讲解了一通无非就是对线程函数赋值给结构体,然后用宏获取该结构来为后续创建线程做准备。到这里应该都很清晰起来了吧,来理一下具体步骤:

  • Step 1osThreadDef 是设置线程名、优先级以及堆栈大小;
  • Step 2、在通过 osThread 获取配置的结构体变量的指针;
  • Step 3、最后作为参数转入 osThreadCreate() 创建线程;

  感谢观看,这里就是 Battery模块 – 邮箱线程 的讲解,如果觉得有帮助,请给文章点个赞吧,让更多的人看到。🌹 🌹 🌹

在这里插入图片描述

  也欢迎你,关注我。👍 👍 👍

  原创不易,还希望各位大佬支持一下,你们的点赞、收藏和留言对我真的很重要!!!💕 💕 💕 最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!下期再见。🎉

更多专栏订阅:

  • 😀 【LeetCode题解(持续更新中)】

  • 🥇 【恒玄BES】

  • 🌼 【鸿蒙系统】

  • 💎 【蓝牙协议栈】

  • 🎃 【死机分析】

  • 👑 【Python脚本笔记】

  • 🚝 【Java Web项目构建过程】

  • 💛 【微信小程序开发教程】

  • 【JavaScript随手笔记】

  • 🤩 【大数据学习笔记(华为云)】

  • 🦄 【程序错误解决方法(建议收藏)】

  • 🔐 【Git 学习笔记】

  • 🚀 【软件安装教程】



订阅更多,你们将会看到更多的优质内容!!

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

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

相关文章

如何用短链接提高内容传播效率?C1N短网址的秘密!

咱都知道&#xff0c;在互联网时代&#xff0c;链接已经成为我们分享内容的标配。但有时候那些长得离谱又复杂的链接&#xff0c;实在是让人头疼。不仅容易出错&#xff0c;还大大降低了内容传播的效率。于是&#xff0c;短链接应运而生&#xff0c;成为现代数字营销中不可或缺…

免费分享一套Java协同过滤推荐算法的SpringBoot+Vue(图书)商城系统【论文+源码+SQL脚本】,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的Java协同过滤推荐算法的SpringBootVue(图书)商城系统&#xff0c;分享下哈。 项目视频演示 【免费】Java协同过滤推荐算法的SpringBootVue(图书)商城系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 伴随着…

【精选】数码论坛系统设计与实现(计算机毕业设计福利,计算机毕业设计参考,JAVA毕业设计)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

环境搭建 | Windows中MinGW-w64及GCC的下载、安装与配置

本文将介绍 GNU、GCC、MinGW 等相关概念&#xff0c;并着重介绍 Windows 中 MinGW-w64 的下载、安装与配置。MinGW-w64 的安装方式有两种&#xff1a;安装程序安装、压缩包安装&#xff0c;压缩包既可在 SourceForge 上下载&#xff0c;也可在 GitHub 上下载。 前导概念 GNU …

模型 ORID思维

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。"结构化思维&#xff0c;深入探讨&#xff0c;明智决策。 1 ORID思维的应用 1.1 提升员工绩效的ORID模型应用 某企业为了提高员工的工作效率和满意度&#xff0c;采用ORID模型进行绩效面谈&…

【Kubernetes】Containerd-得到好物

目录 一、前言二、好物分享1. nerdctl2. buildkit3. k3s4. k9s5. 镜像加速器 三、物料包下载四、总结 一、前言 小伙伴们好久不见鸭&#xff0c;今天小涛分享一些 Containerd容器运维 非常Amazing的工具&#xff0c;老铁们看看操练起来~ 附&#xff1a;最新可用容器镜像加速链…

150mw绿光激光模组主要用途

在现代科技高速发展的今天&#xff0c;激光技术作为一种高精度、高稳定性的技术手段&#xff0c;已经在众多领域展现出了其独特的优势。其中&#xff0c;150mw绿光激光模组作为激光技术的重要分支&#xff0c;以其卓越的性能和广泛的应用前景&#xff0c;备受瞩目。接下来给大家…

MES系统不良品溯源管理:提升产品质量的利器

一、MES系统与不良品溯源管理 MES系统是一种实现车间生产智能化、信息化的管理系统&#xff0c;通过对生产现场的数据采集、处理和分析&#xff0c;为企业提供实时、准确的生产信息。不良品溯源管理是指在生产过程中&#xff0c;对不良品产生的原因进行追踪和分析&#xff0c;…

一文了解内网穿透以及内网穿透工具 Sunny-Ngrok 的使用指南

文章目录 概述简介内网穿透的原理内网穿透的方法内网穿透的应用场景内网穿透的安全考量 Sunny-Ngrok 内网穿透工具简介使用步骤 主要参考 概述 简介 在现代网络架构中&#xff0c;内网穿透&#xff08;也称为 NAT 穿透或端口转发&#xff09;是一项至关重要的技术&#xff0c…

Python | Leetcode Python题解之第375题猜数字大小II

题目&#xff1a; 题解&#xff1a; class Solution:def getMoneyAmount(self, n: int) -> int:f [[0] * (n 1) for _ in range(n 1)]for i in range(n - 1, 0, -1):for j in range(i 1, n 1):f[i][j] j f[i][j - 1]for k in range (i, j):f[i][j] min(f[i][j], k …

探索 AI Agents:从理念到 Python 实际运用

作者:老余捞鱼 原创不易,转载请标明出处及原作者。 写在前面的话: 本文主要介绍了如何利用人工智能代理(AI Agents)从概念到Python中的实际应用,以及如何构建一个内容创作工作流程,通过多个代理协作完成从视频分析到博客撰写的复杂任务,完成后也许这会改变你对人…

【STM32】驱动OLED屏

其实我没买OLED屏哈哈哈&#xff0c;这个只是学习了&#xff0c;没机会实践。 大部分图片来源&#xff1a;正点原子HAL库课程 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目录 1 显示原理 2 读写方式&#xff1a;8080并口 2.1 支持的指令类型 2.2 …

SAP AUTOMAIL-自动发邮件功能

总结 针对发送邮件内容封装公用函数&#xff0c;针对不同业务场景即可实现AUTO MAIL自动触发邮件。 1. 邮件发送内容&#xff1a;正文&#xff0c;附件&#xff0c;超链接等等 1.1 正文可以是一般内容或表格明细清单&#xff0c;涉及到很多格式的设置&#xff0c;用HTML格式…

SSM网上人才招聘系统—计算机毕业设计源码23541

目 录 摘要 1 绪论 1.1研究意义 1.2研究背景 1.3研究原因 1.4 ssm框架介绍 1.5论文结构与章节安排 2 网上人才招聘系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1数据增加流程 2.2.2数据修改流程 2.2.3数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2…

《黑神话:悟空》游戏中的江苏元素

《黑神话&#xff1a;悟空》作为一款以中国经典文学小说《西游记》为基础创作的动作游戏&#xff0c;不仅在游戏剧情和角色设计上深受原著影响&#xff0c;还在游戏场景和元素中融入了大量的中国传统文化&#xff0c;其中不乏江苏地区的特色元素。以下是对游戏中江苏元素的详细…

音频格式转换免费软件有哪些?实用转换工具大揭秘

不知道大家在日常生活中&#xff0c;会不会跟我一样经常遇到需要将音频文件从一种格式转换为另一种格式的情况呢&#xff1f;无论是为了在不同的设备上播放&#xff0c;还是为了节省存储空间&#xff0c;音频转换软件都显得尤为重要。 我最近发现&#xff0c;市面上有许多音频…

力扣1703.得到连续K个1的最少相邻交换次数

力扣1703.得到连续K个1的最少相邻交换次数 中位数贪心 前缀和 设pi qi - i&#xff0c;则问题变为所有pi到x的距离和的最小值 同时x应取pi的中位数 因此枚举i作为最左端的1&#xff0c;求最小值即可 推出距离和公式&#xff1a;s[i] s[ik] - s[ik/2]2 - p[ik/2](k%2) …

pytorch深度学习基础 8 (使用PyTorch的内置功能和默认参数来构建和训练一个简单的线性模型)

co 上面几节都是自定义了很多东西&#xff0c;比如模型的权重&#xff0c;偏置的大小&#xff0c;学习率&#xff0c;损失函数等等&#xff0c;但是实际上pytorch有很多内置的函数以及默认的参数可以对我们的模型部分进行替换&#xff0c;效果也是非常好的&#xff0c;今天我们…

客户信任的秘密武器:为什么每个网站都需要SSL证书?

SSL证书&#xff0c;是网络安全的一把钥匙&#xff0c;它不仅能够锁住数据的安全&#xff0c;还能够建立起用户与网站之间的信任桥梁。在这个数字化日益发展的时代&#xff0c;每个网站都需要配备SSL证书&#xff0c;其背后的原因是多方面的&#xff0c;涉及到技术、安全、信任…

一文掌握数据要素、数据资源、数据资产、数字资产、数据管理、数据治理、数字资产入表是什么?以及关系

数据要素、数据资源、数据资产、数字资产、数据管理、数据治理、数字资产入表到底是什么呢&#xff1f;他们之间是什么关系呢&#xff1f; 数据要素是构建块&#xff0c;数据资源是这些构建块的集合&#xff0c;而数据资产则是具有价值的资源。数据管理和数据治理则确保这些数据…