当前位置: 首页 > news >正文

IO进程----进程

进程

什么是进程

进程和程序的区别

概念:

程序:编译好的可执行文件

存放在磁盘上的指令和数据的有序集合(文件)

程序是静态的,没有任何执行的概念

进程:一个独立的可调度的任务

执行一个程序分配资源的总称

进程是程序执行的一次过程

进程是动态的,包括创建、调度、执行、消亡

特点:

  1. 系统会为每一个进程分配0-4g的虚拟空间,其中0-3g(用户空间)是每个进程所独有的,

3-4g(内核空间)是所有进程共有的。

进程间通信:

  1. CPU调度进程时会给进程分配时间片(几毫秒~十几毫秒),当时间片用完后,cpu再进行其他进程的调度,实现进程的轮转,从而实现多任务的操作。(没有外界干预的情况下怎么调度进程是CPU随机分配的 )

进程控制块task_struct(了解)

● 进程控制块pcb: 包含描述进程的相关信息

● 进程标识PID:唯一的标识一个进程

主要进程标识:

进程号(PID: Process Identity Number)

父进程号:(Parent Process ID: PPID)

● 进程用户

● 进程状态、优先级

● 文件描述符(记录当前进程打开的文件)

进程段

Linux中的进程大致包括三个段

数据段存放的是全局变量、常数以及动态数据分配的数据空间(如malloc函数取得的空间)等。

正文段:存放的是程序中的代码

堆栈段:存放的是函数的返回地址、函数的参数以及程序中的局部变量 (类比内存的栈区)

进程分类

交互进程:该类进程是由shell控制和运行的。交互进程既可以在前台运行,也可以在后台运行。该类进程经常与用户进行交互,需要等待用户的输入,当接收到用户的输入后,该类进程会立刻响应,典型的交互式进程有:shell命令进程、文本编辑器等

批处理进程:该类进程不属于某个终端,它被提交到一个队列中以便顺序执行。(目前接触不到)

守护进程:该类进程在后台运行。它一般在Linux启动时开始执行,系统关闭时才结束。

进程状态

D uninterruptible sleep (usually IO) 不可中断的睡眠态

R running or runnable (on run queue) 运行态

S interruptible sleep (waiting for an event to complete) 可中断的睡眠态

T stopped by job control signal 暂停态

t stopped by debugger during the tracing 因为调试而暂停

X dead (should never be seen) 死亡态

Z defunct ("zombie") process, terminated but not reaped by its parent 僵尸态

< high-priority (not nice to other users) 高优先级

N low-priority (nice to other users) 低优先级

L has pages locked into memory (for real-time and custom IO) 锁在内存中

s is a session leader 会话组组长

l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)多线程

+ is in the foreground process group 前台进程

没有+时,默认是后台进程

进程状态切换图

进程创建后,进程进入就绪态,当CPU调度到此进程时进入运行态,当时间片用完时,此进程会进入就绪态,如果此进程正在执行一些IO操作(阻塞操作)会进入阻塞态,完成IO操作(阻塞结束)后又可进入就绪态,等待CPU的调度,当进程运行结束即进入结束态。

什么是阻塞和非阻塞?

阻塞(blocking)、非阻塞(non-blocking):可以简单理解为需要做一件事能不能立即得到返回应答,如果不能立即获得返回,需要等待,那就阻塞了,在等待的过程中可以做其它事情。否则就可以理解为非阻塞。

进程的相关命令

ps查看系统中的进程-aux-ef

top动态查看系统中的进程

nice按用户指定的优先级运行进程

renice改变正在运行的进程的优先级

kill给进程发信号

fg将进程切换到前台执行

bg将进程切换到后台执行

jobs查看当前终端的后台进程

补充:优先级调度(笔试可能遇见)

根据进程的优先级进行调度,优先级高的进程先执行。

两种类型:

1. 非剥夺式(非抢占式)优先级调度算法。当一个进程正在处理上运行时,即使有某个更为重要或紧迫的进程进入就绪队列,仍然让正在进行的进程继续运行,直到由于其自身原因而主动让出处理机(任务完成或等待事件),才把处理机分配给更为重要或紧迫的进程。

2. 剥夺式(抢占式)优先级调度算法。当一个进程正在处理机上运行时,若有某个更为重要或紧迫的进程进入就绪队列,则立即暂停正在运行的进程,将处理机分配给更重要或紧迫的进程。

面试题:

1. 下列关于轮询任务调度和可抢占式调度区别描述错误的是?

A. 抢占式调度实现相对较复杂且可能出现低优先级的任务长期得不到调度

B. 轮询调度不利于后面的请求及时得到响应

C. 抢占式调度有利于后面的高优先级的任务也能及时得到响应

D. 抢占式调度优点是其简洁性,它无需记录当前所有连接的状态

原因:抢占式调度相对于轮询调度来说实现相对复杂,需要记录和管理任务的优先级、状态等信息。

2. 会导致进程从执行态变为就绪态的事件是( )。(大明科技)

A. 执行P(wait)操作

B. 申请内存失败

C. 启动I/O设备

D. 被高优先级进程抢占

3. 分配到必要的资源并获得处理机时的进程状态是( )。(大明科技)

A. 就绪状态

B. 执行状态

C. 阻塞状态

进程函数接口

创建进程 fork()

pid_t fork(void);
功能:创建子进程
返回值:成功:在父进程中:返回子进程的进程号 >0在子进程中:返回值为0失败:-1并设置errno
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>int main(int argc, char const *argv[])
{pid_t pid;pid = fork();  //创建了一个子进程if(pid < 0){perror("fork err");return -1;}else if(pid == 0){printf("i am child process\n");while(1);   //为了让子进程不要结束}else{printf("i am parent process\n");while(1);   //为了让父进程不要结束}return 0;
}

特点:

1)子进程几乎拷贝了父进程的全部内容。包括代码、数据、系统数据段中的pc值、栈中的数据、父进程中打开的文件等;但它们的PID、PPID是不同的。

2)父子进程有独立的地址空间,互不影响;当在相应的进程中改变全局变量、静态变量,都互不影响。

3)若父进程先结束,子进程成为孤儿进程,被init进程收养,子进程变成后台进程。

4)若子进程先结束,父进程如果没有及时回收资源,子进程变成僵尸进程(要避免僵尸进程产生)

回收资源

pid_t wait(int *status);
功能:回收子进程资源(阻塞)
参数:status:子进程退出状态,不接受子进程状态设为NULL
返回值:成功:回收的子进程的进程号失败:-1pid_t waitpid(pid_t pid, int *status, int options);
功能:回收子进程资源
参数:pid:>0    指定子进程进程号=-1   任意子进程=0    等待其组ID等于调用进程的组ID的任一子进程<-1   等待其组ID等于pid的绝对值的任一子进程status:子进程退出状态options:0:阻塞 WNOHANG:非阻塞
返回值:正常:结束的子进程的进程号当使用选项WNOHANG且没有子进程结束时:0出错:-1
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>int main(int argc, char const *argv[])
{pid_t pid;pid = fork(); //创建了一个子进程if (pid < 0){perror("fork err");return -1;}else if (pid == 0){printf("i am child process\n");sleep(3); //子进程睡眠3秒之后再结束}else{//wait(NULL); //给任意结束的子进程回收资源,如果没有子进程结束就一直阻塞等待。//waitpid(-1, NULL, 0);  //0: 代表阻塞,此时和wait(NULL);效果一样//waitpid(-1, NULL, WNOHANG); //WNOHANG: 代表非阻塞, 此时有可能回收不到子进程资源从而产生僵尸,所以可以通过循环调用解决。while (1)  //循环调用,直到回收到子进程资源以后再退出{if (waitpid(-1, NULL, WNOHANG) > 0)break;}printf("i am parent process\n");while (1);}return 0;
}

结束进程

void exit(int status);
功能:结束进程,刷新缓存void _exit(int status);
功能:结束进程,不刷新缓存
参数:status是一个整型的参数,可以利用这个参数传递进程结束时的状态。通常0表示正常结束;
其他的数值表示出现了错误,进程非正常结束
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{printf("hello");// exit(0);  //结束进程,刷新缓存_exit(0);   //结束进程,不刷新缓存while (1);//思考: exit和return的区别return 0;
}

exit结束当前进程,return结束当前函数。

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>int fun()
{printf("in fun\n");//exit(0);   //结束当前进程return 0;   //结束当前函数
}int main(int argc, char const *argv[])
{fun();printf("in main\n");return 0;
}

获取进程号

pid_t getpid(void);
功能:获取当前进程的进程号pid_t getppid(void);
功能:获取当前进程的父进程号

例如:父子进程中分别打印这两个进程的进程号

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{pid_t pid;pid = fork(); //创建了一个子进程if (pid < 0){perror("fork err");return -1;}else if (pid == 0){printf("i am child process:%d %d\n", getpid(), getppid());}else{printf("i am parent process: %d %d\n", pid, getpid());}while (1);  //让父子进程都不要结束return 0;
}

exec函数族(了解)

在一个进程中执行另一个程序:

system("clear");

system("ls -l");

system不会代替原来进程,而exec函数族会代替原来进程。

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{printf("hello\n");//system("ls -l");   //原来进程不会被替换,执行完ls -l启动的进程之后继续执行原先进程execl("/bin/ls","ls","-l",NULL);  //原先进程被ls -l启动的进程替换了,所以后面打印语句不执行了printf("world\n");return 0;
}

原型:

#include <unistd.h>

int execl(const char *path, const char *arg, ...);

int execlp(const char *file, const char *arg, ...);

int execle(const char *path, const char *arg,..., char * const envp[]);

int execv(const char *path, char *const argv[]);

int execvp(const char *file, char *const argv[]);

int execvpe(const char *file, char *const argv[],char *const envp[]);

守护进程

Linux以会话(session)、进程组的方式管理进程,每个进程属于一个进程组,也就是多个进程组成一个进程组。会话是一个或多个进程组的集合,通常用户打开一个终端时,系统会创建一个会话。所有通过该终端运行的进程都属于这个会话。终端关闭时,所有相关进程会被结束。但是守护进程却能突破这种限制,不受终端关闭的影响。

守护进程的特点

守护进程是后台进程;

生命周期比较长,从系统启动时开启,系统关闭时结束;

它是脱离控制终端且周期执行的进程。

创建步骤

  1. 创建子进程,父进程退出

让子进程变成孤儿,成为后台进程 fork()

  1. 在子进程中创建新会话

让子进程成为会话组组长并且脱离终端:为了让子进程完全脱离终端;setsid()

  1. 改变进程运行路径为根目录

原因:进程运行的路径不能被删除或卸载 shdir("/")

函数说明:chdir() 将进程当前的工作目录改变成以参数路径所指的目录

  1. 重设文件权限掩码

目的:增大进程创建文件时的权限,提高灵活性;umask(0)

子进程继承了父进程的文件权限掩码,给该子进程使用文件带来一定的影响,因此把文件 权限掩码设置为0,可以增强该守护进程的灵活性。

  1. 关闭文件描述符

原因:子进程继承了父进程的一些已经打开了的文件,这些被打开的文件可能永远不会被 守护进程访问,但它们一样占用系统资源,而且还可能导致所在的文件系统无法被卸载。

将不需要的文件关闭 close()

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include <sys/stat.h>int main(int argc, char const *argv[])
{pid_t pid = fork();if(pid<0){perror("fork err");return -1;}if(pid == 0){setsid();chdir("/");umask(0);for(int i=0;i<3;i++) //关闭默认打开的0 1 2close(i);while (1);}else {exit(0);}return 0;
}

练习:创建一个守护进程,循环间隔1s向文件中写入一串字符“hello”
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>int main(int argc, char const *argv[])
{pid_t pid;pid = fork();if (pid < 0){perror("fork err");return -1;}else if (pid == 0){int fd = open("log.txt", O_RDWR | O_CREAT | O_TRUNC, 0777);if (fd < 0){perror("open err");return -1;}setsid();chdir("/");umask(0);for (int i = 0; i < 3; i++)close(i);while (1){write(fd, "hello", 5);sleep(1);}}else{exit(0);}return 0;
}

总结守护进程:

● 守护进程是一个生存周期较长的进程,通常独立于控制终端并且周期性的执行某种任务或者等待处理某些待发生的事件

● 大多数服务都是通过守护进程实现的

● 关闭终端,相应的进程都会被关闭,而守护进程却能够突破这种限制

相关文章:

IO进程----进程

进程 什么是进程 进程和程序的区别 概念&#xff1a; 程序&#xff1a;编译好的可执行文件 存放在磁盘上的指令和数据的有序集合&#xff08;文件&#xff09; 程序是静态的&#xff0c;没有任何执行的概念 进程&#xff1a;一个独立的可调度的任务 执行一个程序分配资…...

【机器学习实战高阶】基于深度学习的图像分割

机器学习项目图像分割 你可能已经注意到&#xff0c;大脑如何快速高效地识别并分类眼睛感知到的事物。大脑以某种方式进行训练&#xff0c;以便能够从微观层面分析所有内容。这种能力有助于我们从一篮子橙子中分辨出一个苹果。 计算机视觉是计算机科学的一个领域&#xff0c;…...

「免填邀请码」赋能各类APP,提升转化率与用户体验

在当前移动互联网的高速发展下&#xff0c;用户获取和留存已成为各类APP成功的关键。传统的注册流程虽然能够有效识别用户来源并进行用户管理&#xff0c;但随着市场竞争的激烈&#xff0c;复杂的注册和绑定步骤往往会成为用户流失的瓶颈。免填邀请码技术&#xff0c;结合自研的…...

基于海思soc的智能产品开发(视频的后续开发)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们讨论了camera&#xff0c;也讨论了屏幕驱动&#xff0c;这些都是基础的部分。关键是&#xff0c;我们拿到了这些视频数据之后&#xff0c;…...

创建 pdf 合同模板

创建 pdf 合同模板 一、前言二、模板展示三、制作过程 一、前言 前段时间要求创建“pdf”模板&#xff0c;学会了后感觉虽然简单&#xff0c;但开始也折腾了好久&#xff0c;这里做个记录。 二、模板展示 要创建这样的模板 三、制作过程 新建一个“Word”&#xff0c;这里命…...

2024 年度学习总结

目录 1. 前言 2. csdn 对于我的意义 3. 写博客的初衷 3.1 现在的想法 4. 写博客的意义 5. 关于生活和博客创作 5.1 写博客较于纸质笔记的优势 6. 致 2025 1. 前言 不知不觉, 来到 csdn 已经快一年了, 在这一年中, 我通过 csdn 学习到了很多知识, 结识了很多的良师益友…...

CSS笔记基础篇02——浮动、标准流、定位、CSS精灵、字体图标

黑马程序员视频地址&#xff1a; 前端Web开发HTML5CSS3移动web视频教程https://www.bilibili.com/video/BV1kM4y127Li?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes&p70https://www.bilibili.com/video/BV1kM4y127Li?vd_source…...

C++ 面向对象(继承)

三、继承 3.1 继承的概念 基于一个已有的类 去重新定义一个新的类&#xff0c;这种方式我们叫做继承 关于继承的称呼 一个类B 继承来自 类 A 我们一般称呼 A类&#xff1a;父类 基类 B类: 子类 派生类 B继承自A A 派生了B 示例图的语法 class vehicle // 车类 {}class …...

Top期刊算法!RIME-CNN-BiLSTM-Attention系列四模型多变量时序预测

Top期刊算法&#xff01;RIME-CNN-BiLSTM-Attention系列四模型多变量时序预测 目录 Top期刊算法&#xff01;RIME-CNN-BiLSTM-Attention系列四模型多变量时序预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 基于RIME-CNN-BiLSTM-Attention、CNN-BiLSTM-Attention、R…...

数据结构 数组

1. 常见的错误 这里我要特别纠正一个“错误”。我在面试的时候&#xff0c;常常会问数组和链表的区别&#xff0c;很多人都回答说&#xff0c;“链表适合插入、删除&#xff0c;时间复杂度O(1)&#xff1b;数组适合查找&#xff0c;查找时间复杂度为O(1)”。 实际上&#xff…...

Kivy App开发之UX控件Bubble气泡

kivy提供了一个提示气泡的小控件Bubble,使用时可以指定气泡箭头的方向以及显示的图像,还可以作为容器添加其他小控件。 常用属性如下 属性说明orientation气泡内子项的排序方式,可设置为vertical或horizontal,默认horizontalarrow_pos箭头相对于气泡的位置,可设置为left_…...

从零到一:打造属于你的AI智能体,支持本地部署

国外卷智能体&#xff0c;国内也都在搞 AI Agent&#xff0c;2025 年也将成为 Agent 的元年。构建智能体主要两种情况&#xff0c;一个是工作流模式&#xff0c;另外一种是直接开发应用&#xff0c;接下来分别给大家介绍一下两种产品和构建过程。工作流模式&#xff0c;以 Coze…...

成就与远见:2024年技术与思维的升华

个人主页&#xff1a;chian-ocean 前言: 2025年1月17日&#xff0c;2024年博客之星年度评选——创作影响力评审的入围名单公布。我很荣幸能够跻身Top 300&#xff0c;虽然与顶尖博主仍有一定差距&#xff0c;但这也为我提供了更加明确的发展方向与指引。展望崭新的2025年&…...

深搜与回溯——扫地机器人问题解析与代码实现

一、题目内容 题目描述 扫地机器人在一个 nm 的网格中从左上角&#xff08;1,1&#xff09;开始清扫。它按照以下规则移动&#xff1a; 如果当前位置的右边&#xff08;同一行&#xff0c;下一列&#xff09;没有被清扫过&#xff0c;它会向右移动。 如果右边无法移动&#xf…...

【大数据2025】Hadoop 万字讲解

文章目录 一、大数据通识大数据诞生背景与基本概念大数据技术定义与特征大数据生态架构概述数据存储数据计算与易用性框架分布式协调服务和任务调度组件数仓架构流处理架构 二、HDFSHDFS 原理总结一、系统架构二、存储机制三、数据写入流程四、心跳机制与集群管理 安全模式&…...

win内核内部直接irp读取文件写入文件

#include <ntifs.h> #include <ntddk.h> #define TAG_NAME tlfF // FltF in reverse #define BUFFER_SIZE PAGE_SIZE // 驱动设备扩展结构 typedef struct _DEVICE_EXTENSION { PDEVICE_OBJECT DeviceObject; UNICODE_STRING DeviceName; UNICODE_STRIN…...

1. 基于图像的三维重建

1. 基于图像的三维重建 核心概念三维重建中深度图、点云的区别&#xff1f;深度图点云总结 深度图到点云还需要什么步骤&#xff1f;1. **获取相机内参**2. **生成相应的像素坐标**3. **计算三维坐标**4. **构建点云**5. **处理颜色信息&#xff08;可选&#xff09;**6. **去除…...

如何确保Python爬虫不违反微店规定

在使用Python爬虫获取微店商品详情时&#xff0c;确保爬虫行为符合微店的规定和相关法律法规至关重要。以下是一些关键步骤和注意事项&#xff0c;帮助你合法合规地使用爬虫技术&#xff1a; 一、遵守法律法规 在使用爬虫技术时&#xff0c;必须严格遵守《网络安全法》、《个…...

Spring Event和MQ的区别和使用场景

概念 Spring事件&#xff08;Spring Event&#xff09;是Spring框架的一项功能&#xff0c;它允许不同组件之间通过发布-订阅机制进行解耦的通信。 MQ一般是一个独立的中间件&#xff0c;它可以通过消息队列对消息进行传递和存储&#xff0c;生产者将消息发送到MQ&#xff0c;…...

SpringBoot:websocket 实现后端主动前端推送数据

简单说明下websocket实用场景。 实时通信领域&#xff1a;社交聊天弹幕多玩家游戏协同编辑股票基金实时报价体育实况更新视频会议/聊天基于位置的应用在线教育智能家居等需要高实时性的场景 一、服务端代码 pom.xml&#xff1a; <dependencies><dependency><…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...