跳转至

博客

VIPT 与缓存大小和页表大小的关系

VIPT(Virtual Index Physical Tag)是 L1 数据缓存常用的技术,利用了虚拟地址和物理地址的 Index 相同的特性,得以优化 L1 数据缓存的读取。但是 VIPT 的使用,与页表大小和 L1 数据缓存大小都有关系。这篇博客探讨一下,VIPT 技术背后的一些问题。

反向代理的 Partial Transfer 问题

反向代理已经是无处不在,但是如果反向代理没有根据使用场景调优,或者出现了一些异常,可能会带来不好的用户体验,并且现象十分奇怪,例如访问某 GitLab 实例的时候,偶尔会出现页面加载不完整的情况。

这些问题困扰了我们很久,到最后才发现,原来问题在反向代理上。下面就来回顾一下事情的经过。

包管理器打包命令速查

随着 Linux 使用逐渐深入,开始尝试参与到一些发行版/包管理器的维护当中。在此记录一下打包相关命令,方便自己速查。

Apple 处理器

M 系列

名称 CPU 核心 GPU 核心 神经网络引擎 内存带宽 内存大小
M1 4+4 7/8 16 8GB/16GB
M1 Pro 6+2/8+2 14/16 16 200GB/s 16GB/32GB
M1 Max 8+2 24/32 16 400GB/s 32GB/64GB
M1 Ultra 16+4 48/64 32 800GB/s 64GB/128GB
M2 4+4 8/10 16 100GB/s 8GB/16GB/24GB
M2 Pro 6+4/8+4 16/19 16 200GB/s 16GB/32GB
M2 Max 8+4 30/38 16 400GB/s 32GB/64GB/96GB
M2 Ultra 16+8 60/76 32 800GB/s 64GB/128GB/192GB
M3 4+4 10 16 100GB/s 8GB/16GB/24GB
M3 Pro 5+6/6+6 14/18 16 150GB/s 18GB/36GB
M3 Max 10+4/12+4 30/40 16 300GB/s/400GB/s 36GB/48GB/64GB/96GB/128GB

来源:

Clang 如何支持 CUDA 程序

前言

编译 CUDA 程序的主要工具是 NVIDIA 提供的闭源编译器 NVCC,但实际上,NVCC 是基于 LLVM 开发的(来源:NVIDIA CUDA Compiler),NVIDIA 也把 NVCC 其中一部分逻辑贡献给了 LLVM 上游,使得 Clang 也可以在 CUDA 的配合下编译 CUDA 程序。这篇博客尝试研究 Clang/LLVM 如何实现 CUDA 程序的编译,主要是 Clang 前端部分,后端部分,也就是从 LLVM IR 到 NVPTX 的这一步还没有进行深入的研究。

WSL2 内部实现探究

背景

最近看到 Windows Subsystem for Linux September 2023 update 声称 WSL2 最新的预览版本支持让 Linux 和 Windows 一定程度上共享网络地址空间,就像 WSL1 那样:

  • IPv6 support
  • Connect to Windows servers from within Linux using the localhost address 127.0.0.1
  • Connect to WSL directly from your local area network (LAN)
  • Improved networking compatibility for VPNs
  • Multicast support

因此比较想知道这是怎么做到的,但目前我手上还没有预览版本的 windows,因此目前先研究 WSL2 已有的功能是如何实现的,未来再回来更新这一部分。

Linux 内核格式与启动协议

背景

之前在各种场合遇到过各种 Linux 内核的文件名或格式,例如:

  • vmlinux
  • vmlinuz
  • uImage
  • bzImage
  • uImage

即使是同样的文件名,格式可能也是不一样的,相应的启动协议也可能不一样。这篇博客尝试结合 Linux,各种 Bootloader(QEMU,EDK-II,U-Boot,OpenSBI)的代码来研究不同的 Linux 二进制格式以及启动协议。

Podman 和 Docker Rootless 实践

最近在配置公用机器的环境,需求是很多用户需要使用 docker,但是众所周知,有 docker 权限就等于有了 root 权限,因此正好想尝试一下现在的 Rootless 容器化方案,例如 docket rootless 和 podman。

在 QEMU 中运行 OpenBMC

背景

最近想给某台机器配一个 BMC,于是调研 OpenBMC 发行版,但是还没有找到可以买到的合适的 BMC,因此先在虚拟机中进行尝试。

SPEC CPU 2006 性能测试

背景

最近在网上看到龙芯 3A6000 的 SPEC CPU 2006 性能评测数据,想着自己也可以在手上的一些平台上测一测,把测试的过程记录在本文。

记录一次 CentOS AArch64 7 到 8 的升级

背景

有一台 AArch64 机器安装了 CentOS 7,想要升级到 CentOS 8,这篇博客主要讲讲折腾的整个过程,而不是教程:如果真要说,就是不要升级 CentOS 大版本,直接重装吧。如果真的想折腾,可以看看下面的内容。

VFIO - Virtual Function I/O

背景

VFIO 是 Linux 内核中的一个功能,目的是把 PCIe 设备暴露给用户态的程序,进而可以暴露给虚拟机内的系统,也就是常说的虚拟机 PCIe 直通。为了保证安全性,VFIO 还会配置好 IOMMU,保证用户态程序无法利用设备的 DMA 访问到其他地址空间的数据。

本文探讨 VFIO 暴露的用户态 API 以及如何在用户态中使用 VFIO 直接控制 PCIe 设备。

Montgomery 模乘

背景

在密码学中,经常会涉及到模乘操作:\(a * b \bmod N\)。朴素的实现方法是,先求出 \(a * b\),再对 N 进行除法,那么余数就是模乘的结果。

但由于此时的 \(a\) \(b\) \(N\) 三个数都很大,在计算机上需要用大整数来表示,而大整数的乘法和除法都是需要耗比较多的时间的。如果用 Schönhage–Strassen 算法,计算两个 \(n\) 位大整数的乘法需要的时间是 \(O(n \log(n) \log(\log(n)))\)

定义

Montgomery 模乘是一种提高模乘的性能的方法。具体地,Montgomery 模乘需要一个参数 \(R\) 满足 \(R\)\(N\) 互质,且 \(R > N\),那么 Montgomery 模乘实现的是如下计算:

\[ M(a, b) = a * b * R^{-1} \bmod N \]

写一个 bash zsh 和 fish 都能跑的脚本

背景

bash 和 zsh 都实现了 POSIX shell 标准,因此写脚本的时候,比较容易兼容这两种常见的 shell。但现在 fish 也很流行,而 fish 不符合 POSIX shell 标准,很多地方语法多不兼容,能否写一个脚本,可以用 bash,zsh 和 fish 跑?

# The following commands should work
bash test.sh
zsh test.sh
fish test.sh

把博客生成器从 Hugo 迁移到 Mkdocs

距离上一次 Jekyll 迁移到 Hugo 已经过去了四年,这次正好 mkdocs-material 发了新的 beta 版本,加入了对博客的支持,所以就当小白鼠,把博客迁移到了 Mkdocs + Mkdocs-Material。

这次迁移比较顺利,除了 tag 和 category 少了一些页面以外,原来的文章的链接都是正常的。为什么要迁移呢,主要是最近写各种文档,Mkdocs 用的比较多,但是 Mkdocs 的 Markdown 很多地方和 Hugo 不太一样,下面列一些最难以忍受的 Hugo 的问题:

  1. 数学公式:Hugo 的 \ 需要转义,导致很多地方写数学公式都很麻烦,然后因为我经常要在 Hugo 和 Mkdocs 之间复制 Markdown,此时就需要很多手动工作。
  2. 资源路径:Hugo 的资源路径默认都是绝对路径,要引用其他文章的话,要么用啰嗦的 relref,要么就写绝对路径,比较头疼。Mkdocs 就很好,自动检测,帮我计算出实际的地址。

迁移的时候有很多细节上的不同,不过基本靠 VSCode 的正则表达式替换解决了。

不过,Mkdocs 又出现了 Jekyll 的老问题,就是性能比较差。当然了,不一定是 Mkdocs 本身的问题,也可能是 Mkdocs-Material 加各种插件的问题,目前还有待观察。无论如何,Python 调起来总归是比 Ruby 要容易。希望不要在未来的某一天,由从 Mkdocs 迁移回 Hugo。

ECDSA

ECDSA 是一个基于椭圆曲线的签名算法,使用时需要确定一个椭圆曲线,以及它的 base point \(G\),且 \(G\) 的阶是素数 \(n\)。ECDSA 支持如下的操作:

  1. 生成签名
  2. 验证签名
  3. 从签名和明文推导出公钥

生成树协议

本文的内容已经整合到知识库中。

Spanning Tree Protocol

STP(Spanning Tree Protocol)可以在 802.1D-1998 第 8 章中找到。STP 协议工作在交换机上,需要根据交换机连接的拓扑,自动计算出一个生成树,并且把不在生成树上的边禁用,这样即使连接的拓扑有环路,禁用以后就没有环了。有了 STP 以后,连接交换机的时候就可以刻意连成环,从而提供冗余。