【深度学习】ND4J-科学计算库
目录
简介
基础用法
基础信息
数组创建
打印数组
变更维度&堆叠
加减乘除
累加/最大/最小
转换操作
矩陈乘法
索引/迭代
深拷贝/引用传递/视图
引用传递
视图
深拷贝
其它
简介
ND4J主要是JVM的科学计算库,内置了很多计算方法,目的是以最低的RAM需求快速运行。主要特点是:
-
一个多功能的n维数组对象。
-
线性代数和信号处理函数。
-
多平台功能,包括GPU。
-
所有主要操作系统: win/linux/osx/android.
-
架构: x86, arm, ppc.
-
Nd4j的主要特点是具有多功能的n维阵列接口INDArray。为了提高性能,Nd4j使用堆外内存来存储数据。INDArray不同于标准Java数组。
基础用法
基础信息
创建数值为0的N维数组
INDArray xx = Nd4j.zeros(10);
System.out.println(xx);//运行结果
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]INDArray x = Nd4j.zeros(3, 4);
System.out.println(x);//运行结果
[[ 0, 0, 0, 0], [ 0, 0, 0, 0], [ 0, 0, 0, 0]]
同理,也支持三维、四维等,可以通过以下方法进行维度信息的查看:
// 数组的轴数(维度)。
int dimensions = x.rank();// 数组的维数。每个维度的大小。
long[] shape = x.shape();// 元素的总数。
long length = x.length();// 数组元素的类型。
DataType dt = x.dataType();
数组创建
要创建INDArray,可以使用ND4J类的静态工厂方法。
Nd4j.createFromArray函数通过重载,支持double、float、int、long类型,同时对各种类型最高支持四维。
double arr_2d[][]={{1.0,2.0,3.0},{4.0,5.0,6.0},{7.0,8.0,9.0}};
INDArray x_2d = Nd4j.createFromArray(arr_2d);double arr_1d[]={1.0,2.0,3.0};
INDArray x_1d = Nd4j.createFromArray(arr_1d);
可以使用函数zeros和ones创建用0和1初始化的数组
可以使用rand函数建用随机值初始化的数组
创建的INDArray的默认数据类型是float,有些重载允许您设置数据类型
INDArray x = Nd4j.zeros(5);
//运行结果
//[ 0, 0, 0, 0, 0], FLOATint [] shape = {5};
x = Nd4j.zeros(DataType.DOUBLE, 5);
//运行结果
//[ 0, 0, 0, 0, 0], DOUBLE// 对于更高的维度,可以提供形状数组。二维随机矩阵示例:
int[] shape = {4, 5};
INDArray x = Nd4j.rand(shape);//运行结果
[[ 0.5669, 0.0576, 0.8701, 0.9598, 0.6470], [ 0.2711, 0.8427, 0.2819, 0.6617, 0.5109], [ 0.0602, 0.2674, 0.6586, 0.9939, 0.4781], [ 0.4099, 0.9503, 0.2227, 0.4738, 0.3759]]
使用arange函数创建一个均匀空间值数组:
INDArray x = Nd4j.arange(5);
// [ 0, 1.0000, 2.0000, 3.0000, 4.0000]INDArray x = Nd4j.arange(2, 7);
// [ 2.0000, 3.0000, 4.0000, 5.0000, 6.0000]
linspace函数允许您指定生成的点数:
//开始数, 停止数, 个数.
INDArray x = Nd4j.linspace(1, 10, 5);
// [ 1.0000, 3.2500, 5.5000, 7.7500, 10.0000]// 对函数进行多点评估。
import static org.nd4j.linalg.ops.transforms.Transforms.sin;
INDArray x = Nd4j.linspace(0.0, Math.PI, 100, DataType.DOUBLE);
INDArray y = sin(x);
打印数组
如上图的例子,INDArray支持Java的toString()方法,可以直接通过System.out.println打印除结果
变更维度&堆叠
可以通过reshap函数进行维度的变更
int [] shape = {4,3};
//2维数组
x = Nd4j.arange(12).reshape(shape);
/*
[[ 0, 1.0000, 2.0000], [ 3.0000, 4.0000, 5.0000], [ 6.0000, 7.0000, 8.0000], [ 9.0000, 10.0000, 11.0000]]
*/
如果本身数据的数组不足以填满新的维度,则会报ND4JIllegalStateException异常
int [] shape = {4,3};
//2维数组
INDArray x = Nd4j.arange(11).reshape(shape);//运行结果
//org.nd4j.linalg.exception.ND4JIllegalStateException: New shape length doesn't match original length: [12] vs [11]. Original shape: [11] New Shape: [4, 3]
INDArray x = Nd4j.rand(3,4);
x.shape();
// [3, 4]INDArray x2 = x.ravel(); //转化成一列
x2.shape();
// [12]INDArray x3 = x.reshape(6,2).shape();
x3.shape();
//[6, 2]//注意x、x2和x3共享相同的数据。
x2.putScalar(5, -1.0);System.out.println( x);
/*
[[ 0.0270, 0.3799, 0.5576, 0.3086], [ 0.2266, -1.0000, 0.1107, 0.4895], [ 0.8431, 0.6011, 0.2996, 0.7500]]
*/System.out.println( x2);
// [ 0.0270, 0.3799, 0.5576, 0.3086, 0.2266, -1.0000, 0.1107, 0.4895, 0.8431, 0.6011, 0.2996, 0.7500]System.out.println( x3);
/*
[[ 0.0270, 0.3799], [ 0.5576, 0.3086], [ 0.2266, -1.0000], [ 0.1107, 0.4895], [ 0.8431, 0.6011], [ 0.2996, 0.7500]]
*/
可以使用vstack和hstack方法将数组堆叠在一起。
INDArray x = Nd4j.rand(2,2);
INDArray y = Nd4j.rand(2,2);x
/*
[[ 0.1462, 0.5037], [ 0.1418, 0.8645]]
*/y;
/*
[[ 0.2305, 0.4798], [ 0.9407, 0.9735]]
*/Nd4j.vstack(x, y);
/*
[[ 0.1462, 0.5037], [ 0.1418, 0.8645], [ 0.2305, 0.4798], [ 0.9407, 0.9735]]
*/Nd4j.hstack(x, y);
/*
[[ 0.1462, 0.5037, 0.2305, 0.4798], [ 0.1418, 0.8645, 0.9407, 0.9735]]
*/
加减乘除
使用INDArray方法对数组执行操作。
加法: arr.add(...), arr.addi(...)减法: arr.sub(...), arr.subi(...)乘法: arr.mul(...), arr.muli(...)除法 : arr.div(...), arr.divi(...)
对数组进行加减乘除操作,有两种类型
【1】in-place :在原有数组基础上变更,如add、sub
【2】复制:创建新的数组,将结果放在新数组中,如addi、subi
//复制
//返回一个新数组,并将标量添加到arr的每个元素。
arr_new = arr.add(scalar);
//返回一个新数组,它是arr和其他arr元素级别的加法。
arr_new = arr.add(other_arr); //In-place
arr_new = arr.addi(scalar);
arr_new = arr.addi(other_arr);
in-place运算符可以方便地将操作链接在一起。尽可能使用(in-place)运算符来提高性能,因为
复制运算符有新的数组创建开销。
注意,执行加减乘除操作时,必须确保基础数据类型相同。
int [] shape = {5};
INDArray x = Nd4j.zeros(shape, DataType.DOUBLE);
INDArray x2 = Nd4j.zeros(shape, DataType.INT);
INDArray x3 = x.add(x2);
// java.lang.IllegalArgumentException: Op.X 和 Op.Y must have the same data type, but got INT vs DOUBLE// 将x2转换为DOUBLE可以解决以下问题:
INDArray x3 = x.add(x2.castTo(DataType.DOUBLE));
累加/最大/最小
INDArray有实现累加/最值操作的方法,如 sum, min, max.
int [] shape = {2,3};
INDArray x = Nd4j.rand(shape);
x;
x.sum();
x.min();
x.max();
/*
[[ 0.8621, 0.9224, 0.8407], [ 0.1504, 0.5489, 0.9584]]
4.2830
0.1504
0.9584
*/
提供维度参数以在指定维度上应用操作:
INDArray x = Nd4j.arange(12).reshape(3, 4);
/*
[[ 0, 1.0000, 2.0000, 3.0000], [ 4.0000, 5.0000, 6.0000, 7.0000], [ 8.0000, 9.0000, 10.0000, 11.0000]]
*/ //每列的总和。
x.sum(0);
//[ 12.0000, 15.0000, 18.0000, 21.0000]//每行最小值
x.min(1);
//[ 0, 4.0000, 8.0000]//每行的累计和,
x.cumsum(1);
/*
[[ 0, 1.0000, 3.0000, 6.0000], [ 4.0000, 9.0000, 15.0000, 22.0000], [ 8.0000, 17.0000, 27.0000, 38.0000]]
*/
转换操作
Nd4j提供熟悉的数学函数,如sin、cos和exp,这些称为转换操作。结果作为INDArray返回。
import static org.nd4j.linalg.ops.transforms.Transforms.exp;
import static org.nd4j.linalg.ops.transforms.Transforms.sqrt;INDArray x = Nd4j.arange(3);
// [ 0, 1.0000, 2.0000]
exp(x);
// [ 1.0000, 2.7183, 7.3891]
sqrt(x);
// [ 0, 1.0000, 1.4142]
矩陈乘法
INDArray也支持矩阵运算,如下:
INDArray x = Nd4j.arange(12).reshape(3, 4);
/*
[[ 0, 1.0000, 2.0000, 3.0000], [ 4.0000, 5.0000, 6.0000, 7.0000], [ 8.0000, 9.0000, 10.0000, 11.0000]]
*/INDArray y = Nd4j.arange(12).reshape(4, 3);
/*
[[ 0, 1.0000, 2.0000], [ 3.0000, 4.0000, 5.0000], [ 6.0000, 7.0000, 8.0000], [ 9.0000, 10.0000, 11.0000]]
*/
// 矩阵乘积.
x.mmul(y);
/*
[[ 42.0000, 48.0000, 54.0000], [ 114.0000, 136.0000, 158.0000], [ 186.0000, 224.0000, 262.0000]]
*///点积
INDArray x = Nd4j.arange(12);
INDArray y = Nd4j.arange(12);
dot(x, y);
//506.0000
索引/迭代
获取某个位置的数据
INDArray x = Nd4j.arange(12);
// [ 0, 1.0000, 2.0000, 3.0000, 4.0000, 5.0000, 6.0000, 7.0000, 8.0000, 9.0000, 10.0000, 11.0000]
//单一元素访问。其他方法: getDouble, getInt, ...
float f = x.getFloat(3);
// 3.0
转化为Java数组
//转换为Java数组。
float [] fArr = x.toFloatVector();
// [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0]
获取指定区间的数据
INDArray x2 = x.get(NDArrayIndex.interval(2, 6));
// [ 2.0000, 3.0000, 4.0000, 5.0000]
在x的副本上:从开始到位置6(不包括),将每2个元素设置为-1.0
//在x的副本上:从开始到位置6(不包括),将每2个元素设置为-1.0
INDArray y = x.dup();
y.get(NDArrayIndex.interval(0, 2, 6)).assign(-1.0);
//[ -1.0000, 1.0000, -1.0000, 3.0000, -1.0000, 5.0000, 6.0000, 7.0000, 8.0000, 9.0000, 10.0000, 11.0000]
y的反向副本
//y的反向副本。
INDArray y2 = Nd4j.reverse(y.dup());
//[ 11.0000, 10.0000, 9.0000, 8.0000, 7.0000, 6.0000, 5.0000, -1.0000, 3.0000, -1.0000, 1.0000, -1.0000]
对于多维数组,应该使用INDArray.get(NDArrayIndex...)。下面的示例演示如何遍历二维数组的行和列。注意,对于2D数组,我们可以使用getColumn和getRow便利方法。
// 在2d数组的行和列上迭代。
int rows = 4;
int cols = 5;
int[] shape = {rows, cols};INDArray x = Nd4j.rand(shape);
/*
[[ 0.2228, 0.2871, 0.3880, 0.7167, 0.9951], [ 0.7181, 0.8106, 0.9062, 0.9291, 0.5115], [ 0.5483, 0.7515, 0.3623, 0.7797, 0.5887], [ 0.6822, 0.7785, 0.4456, 0.4231, 0.9157]]
*/for (int row=0; row<rows; row++) {INDArray y = x.get(NDArrayIndex.point(row), NDArrayIndex.all());}
/*
[ 0.2228, 0.2871, 0.3880, 0.7167, 0.9951]
[ 0.7181, 0.8106, 0.9062, 0.9291, 0.5115]
[ 0.5483, 0.7515, 0.3623, 0.7797, 0.5887]
[ 0.6822, 0.7785, 0.4456, 0.4231, 0.9157]
*/for (int col=0; col<cols; col++) {INDArray y = x.get(NDArrayIndex.all(), NDArrayIndex.point(col));}
/*
[ 0.2228, 0.7181, 0.5483, 0.6822]
[ 0.2871, 0.8106, 0.7515, 0.7785]
[ 0.3880, 0.9062, 0.3623, 0.4456]
[ 0.7167, 0.9291, 0.7797, 0.4231]
[ 0.9951, 0.5115, 0.5887, 0.9157]
*/
深拷贝/引用传递/视图
引用传递
以下用法,仅仅只是指向x的指针,进行了引用传递,并未复制
INDArray x = Nd4j.rand(2,2);
//y和x指向同一个INDArray对象。
INDArray y = x;
视图
一些函数将返回数组的视图,并未进行数组的复制
INDArray x = Nd4j.rand(3,4);
INDArray x2 = x.ravel();
INDArray x3 = x.reshape(6,2);// 修改 x, x2 和 x3
x2.putScalar(5, -1.0); x
/*
[[ 0.8546, 0.1509, 0.0331, 0.1308], [ 0.1753, -1.0000, 0.2277, 0.1998], [ 0.2741, 0.8257, 0.6946, 0.6851]]
*/x2
// [ 0.8546, 0.1509, 0.0331, 0.1308, 0.1753, -1.0000, 0.2277, 0.1998, 0.2741, 0.8257, 0.6946, 0.6851]x3
/*
[[ 0.8546, 0.1509], [ 0.0331, 0.1308], [ 0.1753, -1.0000], [ 0.2277, 0.1998], [ 0.2741, 0.8257], [ 0.6946, 0.6851]]
*/
深拷贝
要复制数组,请使用dup方法。这将为您提供一个包含新数据的新数组。
INDArray x = Nd4j.rand(3,4);
INDArray x2 = x.ravel().dup();//现在只改变x2。
x2.putScalar(5, -1.0);
x
/*
[[ 0.1604, 0.0322, 0.8910, 0.4604], [ 0.7724, 0.1267, 0.1617, 0.7586], [ 0.6117, 0.5385, 0.1251, 0.6886]]
*/x2
// [ 0.1604, 0.0322, 0.8910, 0.4604, 0.7724, -1.0000, 0.1617, 0.7586, 0.6117, 0.5385, 0.1251, 0.6886]
其它
ND4J还有很多科学计算函数,具体可以查看文档
nd4j-api 1.0.0-M2.1 javadoc (org.nd4j)
相关文章:
【深度学习】ND4J-科学计算库
目录 简介 基础用法 基础信息 数组创建 打印数组 变更维度&堆叠 加减乘除 累加/最大/最小 转换操作 矩陈乘法 索引/迭代 深拷贝/引用传递/视图 引用传递 视图 深拷贝 其它 简介 ND4J主要是JVM的科学计算库,内置了很多计算方法,目的…...
2024-01-29 ubuntu 用脚本设置安装交叉编译工具链路径方法,设置PATH环境变量
一、设置PATH环境变量的方法,建议用~/.bash_profile的方法,不然在ssh登录的时候可能没有设置PATH. 二、下面的完整的脚本,里面的echo "export PATH$build_toolchain_path:\$PATH" >> $HOME/.bashrc 就是把交叉编译路径写写到.bashrc设置…...
今年春节很多年轻人选择不买战袍,减少年货置办,「极简过年」,如何看待此现象?
近年来,春节期间出现了一种新的现象,越来越多的年轻人选择不买战袍,减少年货置办,采用“极简过年”的方式度过春节。对于这一现象,不同人有不同的看法。 首先,这种极简过年的方式符合当前社会的一些价值观…...
C语言·贪吃蛇游戏(下)
上节我们将要完成贪吃蛇游戏所需的前置知识都学完了,那么这节我们就开始动手写代码了 1. 程序规划 首先我们应该规划好我们的代码文件,设置3个文件:snack.h 用来声明游戏中实现各种功能的函数,snack.c 用来实现函数,t…...
Flask 入门2:路由
1. 前言 在上一节中,我们使用到了静态路由,即一个路由规则对应一个 URL。而在实际应用中,更多使用的则是动态路由,它的 URL是可变的。 2. 定义一个很常见的路由地址 app.route(/user/<username>) def user(username):ret…...
【C++】 C++入门— 基于范围的 for 循环
C 基于范围的for循环1 使用样例2 使用条件3 完善措施 Thanks♪(・ω・)ノ谢谢阅读!下一篇文章见!!! 基于范围的for循环 1 使用样例 使用for循环遍历数组,我们通常这么写: …...
C++——析构函数
C——析构函数 什么是析构函数 析构函数是C中的一个特殊的成员函数,它在对象生命周期结束时被自动调用,用于执行对象销毁前的清理工作。析构函数特别重要,尤其是在涉及动态分配的资源(如内存、文件句柄、网络连接等)…...
Vue3学习记录(二)--- 组合式API之计算属性和侦听器
一、计算属性 1、简介 计算属性computed(),用于根据依赖的响应式变量的变化,进行自动的计算,并返回计算后的结果。当依赖的响应式变量发生变化时,computed()会自动进行重新计算,并返回最新的计算结果。如果依赖的…...
react-virtualized实现行元素不等高的虚拟列表滚动
前言: 当一个页面中需要接受接口返回的全部数据进行页面渲染时间,如果数据量比较庞大,前端在渲染dom的过程中需要花费时间,造成页面经常出现卡顿现象。 需求:通过虚拟加载,优化页面渲染速度 优点࿱…...
Linux系统各目录作用
/etc文件系统 /etc 目录包含各种系统配置文件,下面说明其中的一些。其他的你应该知道它们属于哪个程序,并阅读该程序的m a n页。许多网络配置文件也在/etc 中。 1. /etc/rc或/etc/rc.d或/etc/rc?.d 启动、或改变运行级时运行的脚本或脚本的目录。 2. /…...
嵌入式系统学习(一)
嵌入式现状(UP经历): 大厂的招聘要求: 技术栈总结: 产品拆解网站: 52audio 方案查询网站iotku,我爱方案网, 主要元器件类型:...
重写Sylar基于协程的服务器(3、协程模块的设计)
重写Sylar基于协程的服务器(3、协程模块的设计) 重写Sylar基于协程的服务器系列: 重写Sylar基于协程的服务器(0、搭建开发环境以及项目框架 || 下载编译简化版Sylar) 重写Sylar基于协程的服务器(1、日志模…...
Linux之系统安全与应用续章
目录 一. PAM认证 1.2 初识PAM 1.2.1 PAM及其作用 1.2.2 PAM认证原理 1.2.3 PAM认证的构成 1.2.4 PAM 认证类型 1.2.5 PAM 控制类型 二. limit 三. GRUB加密 /etc/grub.d目录 四. 暴力破解密码 五. 网络扫描--NMAP 六. 总结 一. PAM认证 1.2 初识PAM PAM是Linux系…...
《HTML 简易速速上手小册》第7章:HTML 多媒体与嵌入内容(2024 最新版)
文章目录 7.1 在HTML中嵌入视频和音频7.1.1 基础知识7.1.2 案例 1:嵌入视频文件7.1.3 案例 2:嵌入音频文件7.1.4 案例 3:创建一个视频和音频混合的播放列表 7.2 使用 <iframe> 嵌入外部内容7.2.1 基础知识7.2.2 案例 1:嵌入…...
【CSS】移动端适配
移动端适配怎么做? 适配的目的是在屏幕大小不同的终端设备拥有统一的界面,让拥有更大屏幕的终端展示更多的内容。 meta viewport (视口) 移动端初始视口的大小默认是980px,因为世界上绝大多数PC网页的版心宽度为980px ,如果网页…...
DFS剪枝算法经典题目-挑选
4954. 挑选 - AcWing题库 给定一个包含 n 个正整数 a1,a2,…,an的集合。 集合中可能存在数值相同的元素。 请你从集合中挑选一些元素,要求同时满足以下所有条件: 被选中元素不少于 2 个。所有被选中元素之和不小于 l 且不大于 r。所有被选中元素之中最大…...
考研经验总结——考试期间
文章目录 一、订房二、看考场三、休息四、考前带宾馆的书五、安全 一、订房 我刚刚看了看,是9.10号订的酒店。你们可以提前向学长学姐打听你的考场在哪个学校(徐州的考生,考省外的学校是在矿大考试,考省内的学校是在江师大&#…...
vue3 源码解析(6)— lifecycle 生命周期的实现
前言 对于 vue3 的生命周期,我们经常性会去疑问,生命周期有哪些呢,它是怎么去实现的, 又是什么时候调用的。 vue3 生命周期有哪些 下面这个表格列出了所有选项式api生命周期钩子和组合式api生命周期钩子,以及他们的…...
three.js CSS2DRenderer、CSS2DObject渲染HTML标签
有空的老铁关注一下我的抖音: 效果: <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red;position: relative;"><…...
SECS/GEM300和半导体e84控制器
SECS(SEMI EQUIPMENT COMMUNICATIONS STANDARD 2)半导体设备通讯标准 GEM(Generic Equipment Model)定义了Fab中各个场景下设备行为及其所使用SECS消息。 GEM300也称为300mm标准,FAB是12寸设备的处理作业规范。主要包…...
一文讲透|盘点2026年标杆级的AI论文网站
一天写完毕业论文在2026年已不再是天方夜谭。以下是2026年最炸裂、实测能大幅提速的AI论文网站神器,覆盖全流程生成、文献处理、降重润色、格式排版四大核心场景,帮你高效搞定毕业论文。 一、全流程王者:一站式搞定论文全链路(一天…...
PHP Intelephense项目结构解析:多工作区、虚拟工作区与远程开发
PHP Intelephense项目结构解析:多工作区、虚拟工作区与远程开发 【免费下载链接】vscode-intelephense PHP intellisense for Visual Studio Code 项目地址: https://gitcode.com/gh_mirrors/vs/vscode-intelephense PHP Intelephense是一款为Visual Studio …...
Twemoji跨平台表情统一渲染方案:构建一致性用户体验的核心技术
Twemoji跨平台表情统一渲染方案:构建一致性用户体验的核心技术 【免费下载链接】twemoji Emoji for everyone. 项目地址: https://gitcode.com/gh_mirrors/twe/twemoji Twemoji作为一款基于Unicode标准的开源表情解决方案,为开发者和产品经理提供…...
30天学会AI工程师|Day 13:Tool Calling 不是高级玩法,它是 Agent 开始有手脚的那一步
你先知道一件事 很多人第一次听到 Tool Calling,会觉得这是很后面的内容,好像得先学完模型、Prompt、框架,再轮到它。 为什么这一步重要 其实从工程视角看,它反而是一个很早就该理解的能力。 因为大模型只会“生成文本”这件事&am…...
Midjourney金属质感渲染实战手册(航天级铝钛合金/做旧铜锈/镜面不锈钢三重进阶)
更多请点击: https://intelliparadigm.com 第一章:Midjourney金属质感渲染的核心原理与演进脉络 金属质感在AI图像生成中属于高阶视觉建模任务,其本质依赖于对微观表面结构、镜面反射路径与环境光交互的隐式学习。Midjourney自V5起引入更精细…...
SABIC塑料与宏裕塑胶的卓越合作:高性能材料的行业应用
导读:在制造业转型升级的关键时期,高性能工程塑料的应用正成为企业提升产品竞争力的核心要素。SABIC塑料与宏裕塑胶的卓越合作,为行业提供了从原料选型到技术落地的完整解决方案,这种强强联合的模式正在重新定义高端材料供应体系。…...
2026年福建莆田大平层全屋高端定制选型指南
一、引言福建莆田近年来经济发展迅速,居民生活水平不断提高,大平层住宅逐渐成为高端改善型住房的热门选择。在全屋高端定制方面,消费者面临着众多品牌的选择。本指南旨在为莆田的大平层业主提供一份合规、靠谱且适配自身需求的高端定制品牌选…...
体验Taotoken全球节点带来的低延迟API调用体感
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 体验Taotoken全球节点带来的低延迟API调用体感 对于需要频繁调用大模型API的开发者而言,除了模型的智能程度࿰…...
ZYNQ启动全解析:从BootROM到你的App,SD卡与QSPI Flash烧录究竟差在哪?
ZYNQ启动全解析:从BootROM到你的App,SD卡与QSPI Flash烧录究竟差在哪? 当一块ZYNQ开发板静静躺在桌面上,按下电源键的瞬间,芯片内部究竟发生了什么?为什么有的工程师选择SD卡启动,而另一些则坚…...
如何快速掌握Pixel设备刷机:新手完整教程与PixelFlasher刷机工具指南
如何快速掌握Pixel设备刷机:新手完整教程与PixelFlasher刷机工具指南 【免费下载链接】PixelFlasher Pixel™ phone flashing GUI utility with features. 项目地址: https://gitcode.com/gh_mirrors/pi/PixelFlasher 你是否曾经因为复杂的命令行刷机操作而感…...
