Abonite'd Smiet

欢迎来到Abonite的世界

更好的部署方式

经历了hexo原始项目文件丢失又找回的惊吓之后,我决定改用github active管理我的blog。因为这种方案需要将全部原始文件上传至github,可以用作备份和版本管理,而以前的一键部署方案依赖hexo在本地生成静态页面再上传,远程git仓库没有原始文件。需要另开分支或仓库存储这些文件。如果没有存,那就要小心文件丢失的风险。

好在,我并不是从零开始构建工程。这里就简单记录一下大概流程:

  • 安装node.js。我安装的是22.19.0版本。这是一个lts版本。在安装过程中,node.js会询问你是否自动安装所需的工具。如果你已经配置好自己电脑的开发环境,千万不要选择这一项,容易把自己的开发环境搞乱。
  • 安装hexo。运行npm install -g hexo-cli
  • 新建文件夹,在命令行进入新建的文件夹,运行hexo init,待运行完成后,运行npm install
  • 运行hexo new post/page新建推文或页面。
  • 将完成编辑的工程push到git的指定仓库。要将仓库设置为github active模式。

使用github active主要需要注意的一点,首先要注意不要将/public文件夹上传,其次要知道如何编写任务脚本。这里,参考hexo官方的编写方法,方便省心。

如果一切设置妥当,当新版本的工程被push到git上时,构建将会自动开始,可以在仓库的active页面看到构建进度和log。待构建完成,即可在指定的url看到。

插入图片

按照官方文档,开启post_asset_folder: true并且打开:

1
2
3
marked:
prependRoot: true
postAsset: true

就应该实现,在新建post时,自动生成一个同名资源文件夹;将要插入的图片放入资源文件夹,并在md文件中引用即可实现插入。

但实际情况是,这种插入方法在使用markdown编辑器编辑时无法预览,且在真实网页上也看不到插入的图片。经过检查,插入的图片经过渲染后并没有被正常替换为public下的路径。

最后通过安装hexo-asset-img和htmlparser2,并在插入图片路径前添加post名实现在编辑时和真实网页都能看到图片。另外要注意图片的文件名,经过hexo转换后,图片的文件名可能发生改变。

插入LaTex

例如:

通过安装hexo-filter-mathjax,并在md文件的属性部分添加mathjax: true达成。

How to optimize your matlab program

Matlab作为一个全能型软件兼解释型语言,在科研、工程设计、仿真模拟等多个领域都具有不可撼动的地位,曾经有人开玩笑道:“matlab除了不能给你生孩子,其它的都能干。相信在座的各位都或多或少使用过matlab。但是,在功能方面可以说神功大成的matlab其实也有一个比较重大的缺陷,那就是慢。做算法的诸位,包括我本人,我相信对matlab强大的功能印象深刻的同时,也会在无数个瞬间突然产生这样一个念头:

如果matlab更快一点就好了。

不同于编译型语言的汇编,C、C++,Go,Rust,解释型语言是带有先天不足的。解释型语言是由解释器运行的,它的特点是就是自由和慢。由于几乎所有的解释型语言都带有自动垃圾回收,所以我们可以轻松愉快地编写各种代码而不用担心变量的作用域和内存泄露等问题,自动垃圾回收会帮助你解决一切;而这种随心所欲的代价就是,由于需要解释器实时地逐行执行语句,以及执行垃圾回收需要时间而导致的效率低下。

那么,有没有办法让matlab变快一些呢?

一个例子

接下来,我将使用一个经典算法的实现向各位读者介绍如何优化你的matlab。这个算法就是FFT-Fast Fourier Transform,快速傅里叶变换。快速傅里叶变换可以帮助我们对一段任意长度的离散信号进行频域分析,也就是说,它是这样一个有魔力的机器,可以将一段信号输入,吐出来的却是一些频率和幅度均不同的正弦波。其在工程与学术界得到了极其广泛的应用,广泛到这个本来看起来非常不可思议的算法已经事实上成为了大量学术理论和工程应用的基石。要知道,这个理论最开始受到拉格朗日的强烈反对,因为他怎么也想不明白任意一个连续函数是如何能被分解成无数个正弦函数的。

这里有一个非常经典的例子。我使用FL Studio写了一段简单的钢琴曲,将导出的音频文件放进Adobe Audition来看一看:

而这是这段钢琴曲在FL Studio中的样子:

我们可以看到,首先频谱窗口中似乎有一条条的横向条纹,它们的高低位置与FL Studio中的音符位置有一定的对应关系。实际上,这就是一个指定音高的钢琴音色产生的频谱,不同于正弦波,钢琴音色是由很多正弦波叠加产生的,也就是说,它是由各种不同频率的音频分量构成的,我们可以在频谱窗口中清晰地看到这一点:每一条较为清晰的横线就是一个可以被明确分辨的频率分量。FFT算法帮助我们做到了这一点,我们的视角从直观的时间-幅度坐标,转移到相对不直观的频率-幅度坐标。

最原始的办法

现在,我们已经搞明白了算法。假设你是一个新人,你刚刚学会matlab代码要如何编写,此时,你就可以照着算法一步步地实现自己的FFT模块了。在这里我们希望这个FFT模块输入一个N行的列向量,其中每一行都是一个复数。我们不要求N必须是2的幂次方,如果N不足2的幂次方,我们希望FFT能够自行在这个列向量的结尾补0,使其能够达到距离N最近的2的幂次方。

另外,我们也希望能够通过第二个参数手动指定FFT点数,同样的,当输入的列向量的行数N不足最大点数时,自动补0到最大点数,然后再对补0之后的序列做FFT。这样,我们就有了一个比较灵活的FFT模块,供我们下一步的开发和使用了。

喝点咖啡,写点Java

Matlab与Java的关系是及其紧密的。Matlab向Java开放了大量的底层接口,用户在进行开发时可以选择直接将Java代码嵌入Matlab中。只要你的电脑里同时安装了matlab和jdk,无需过多操作,你就可以直接体验java带给你的便利。不过,MATLAB对Java的版本有要求,具体可以到这里查看。推荐大家使用OpenJDK,下载zip版本,这个版本的组件似乎更加齐全。解压后,添加一个环境变量:

1
%JAVA_HOME% = 解压路径

并且将

1
"%JAVA_HOME%\bin"

添加到Path下。如果是windows 11,不必写双引号。

现在,打开一个windows terminal,执行java -version看看结果,如果有输出,且输出的版本与你下载的版本对应,那么你已经把Java配置好了。

然后,打开你的matlab,在命令行执行

1
jenv("system")

matlab就会自动调用你配置好的java。

C语言如何

如果你想试试C语言的mex,体验更加便利的matlab与C语言的交互,你得先配置C语言环境。同样的,matlab不同版本对C语言编译器的版本有要求。官方似乎更推荐Mingw-C,不过我使用了MSVC。具体各个编译器版本,可以到这里查看。

为了防止安装VS这个巨无霸,我参照了这个教程,保证我最小安装一个可用的MSVC编译器,而不用安装动辄数十数百G的整个VS。安装好后,如果一切正常,打开matlab,运行

1
mex -setup cpp

就应该能够成功配置。

——近朱者赤,近墨者黑


有关MACPU ISA的具体设计,可以参见MACPU-FPGA仓库中的Instruction.md


CPU,从功能而言,是很简单的:能够按部就班地顺序执行运算步骤,括弧,如果性能再高点就好了。如果仅考虑按部就班地执行运算步骤,那么世界很美好——最古老的CPU被设计出来的时候,就使用来干这个的,显然,类似于Intel 4004之流的CPU也不可能有太高的性能,对比如今动辄数吉赫兹频率的CPU,其最高工作频率(740KHz)是在是太不够看了。

一般来说,要设计一款CPU,首先要决定其可以执行的指令。这些指令的数量一般会有很多,不过,我们也可以仅使用个位数的指令来设计一款CPU,但是那将会为配套的编译器带来一些问题。这些指令的集合就是指令集架构,它解决了CPU可以做什么的问题。但是对于一款CPU,仅有指令集架构是不够的,我们还需要提供一些其它的信息:

  • 指令的编码格式:CPU是无法直接理解人的语言的。如果你对它说,告诉我1 + 1等于几,它是玩玩无法做出回应的。它只能理解数字信号:0、1和它们的组合。因此,我们需要将每一条指令翻译成0、1和它们的组合,而如何进行翻译则完全由设计者决定。
  • 寄存器:寄存器是CPU中用来临时存储数据的东西。受限于电路实现,这些东西的存在是必须的。
  • 异常处理:当CPU发现错误的时候,应该做出怎样的反应?错误将会被如何进行处理?由此引发的一系列问题直接关系到CPU工作是否稳定。
  • 中断:当发生突发事件时,CPU应该怎样应对?
  • ……

这一些列的信息,就可以开始规划CPU,把问题由做什么进一步地推进到需要怎么做。这些信息,像一个框架,为CPU的具体实现提供了重要参考依据,我们一般称其为“ISA”,即Instruction-Set Architecture,指令集体系结构。

由于ISA将会牵扯到很多方面的具体实现,因此,在设计ISA时就应该同时考虑到这些因素。一个设计得足够好的ISA一定可以帮助同时统筹软件实现和物理逻辑实现的各方各面。可以说,ISA才是整个CPU和系统实现的灵魂,所以在开始设计ISA时就下足够的功夫无疑是一件值得的事情。

在实际设计ISA时,以我个人的经验而言,时长需要考虑如下问题:

  • 是使用简单的物理实现,简单的指令集,配合复杂的编译器优化,还是使用复杂的物理实,复杂的指令集,现配合简单的编译器优化?
  • 对于一条具体的指令,当有多种具体的物理实现方法时,应该怎么选择?
  • 面对持续增长的算力需求,在更新换代CPU时,应该如何保持ISA的兼容性,并且添加新的东西?
  • ……

CPU发展的路程走过了五十甚至六十年,而各大团体,公司和组织对这些问题都已经有了深入的研究,目前,大家普遍认为RISC(精简指令集)的执行效率要明显高于CISC(复杂指令集),在这方面,走在世界前列的无疑是RISC-V,其极低的功耗,完全开源的设计理念正在引来世界各大公司的广泛关注。

MACPU设计记录

要踩的坑,踩过的坑

想要利用自己的小破板子做点什么,过于高大上的东西自然没什么想法,不过一些小玩意还是可以的。

0%