2 Commits

Author SHA1 Message Date
3053b83bbf feat: a lot of notebooks. 2025-08-31 12:39:18 +08:00
457316971c draft: six notebooks 2025-06-16 00:45:16 +08:00
87 changed files with 104 additions and 297 deletions

View File

@@ -15,9 +15,6 @@ trim_trailing_whitespace = true
[project.json]
indent_size = 2
[*.{yaml,yml}]
indent_size = 2
# C# and Visual Basic files
[*.{cs,vb}]
charset = utf-8-bom

1
.gitattributes vendored
View File

@@ -1,5 +1,4 @@
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.avif filter=lfs diff=lfs merge=lfs -text
*.webp filter=lfs diff=lfs merge=lfs -text

View File

@@ -1,36 +1,33 @@
name: Build blog docker image
on:
push:
branches:
- master
push:
branches:
- master
jobs:
Build-Blog-Image:
runs-on: archlinux
steps:
- name: Check out code.
uses: https://mirrors.rrricardo.top/actions/checkout.git@v4
with:
lfs: true
- name: Build project.
run: |
cd YaeBlog
dotnet publish
- name: Build docker image.
run: |
proxy
podman pull mcr.microsoft.com/dotnet/aspnet:9.0
unproxy
cd YaeBlog
podman build . -t ccr.ccs.tencentyun.com/jackfiled/blog --build-arg COMMIT_ID=$(git rev-parse --short=10 HEAD)
- name: Workaround to make sure podman-login working.
run: |
mkdir /root/.docker
- name: Login tencent cloud docker registry.
uses: https://mirrors.rrricardo.top/actions/podman-login.git@v1
with:
registry: ccr.ccs.tencentyun.com
username: 100044380877
password: ${{ secrets.TENCENT_REGISTRY_PASSWORD }}
auth_file_path: /etc/containers/auth.json
- name: Push docker image.
run: podman push ccr.ccs.tencentyun.com/jackfiled/blog:latest
Build-Blog-Image:
runs-on: archlinux
steps:
- uses: https://mirrors.rrricardo.top/actions/checkout.git@v4
name: Check out code
with:
lfs: true
- name: Build project
run: |
cd YaeBlog
dotnet publish
- name: Build docker image
run: |
cd YaeBlog
podman build . -t registry.cn-beijing.aliyuncs.com/jackfiled/blog:latest --build-arg COMMIT_ID=$(git rev-parse --short=10 HEAD)
- name: Workaround to make sure podman login succeed
run: |
mkdir /root/.docker
- name: Login aliyun docker registry
uses: https://mirrors.rrricardo.top/actions/podman-login.git@v1
with:
registry: registry.cn-beijing.aliyuncs.com
username: 初冬的朝阳
password: ${{ secrets.ALIYUN_PASSWORD }}
auth_file_path: /etc/containers/auth.json
- name: Push docker image
run: podman push registry.cn-beijing.aliyuncs.com/jackfiled/blog:latest

View File

@@ -1,29 +0,0 @@
<div class="flex flex-wrap justify-center gap-12 max-w-md md:max-w-lg">
<div class="relative w-40 h-48 md:w-48 md:w-48 overflow-hidden
transition-all duration-300 ease-out hover:scale-125 group">
<img
src="./images/wechat-code.jpeg"
alt="微信赞赏码"
class="w-full h-full object-cover"
/>
<div class="absolute -bottom-8 left-0 right-0 text-center
text-white bg-black opacity-60 text-sm font-medium
backdrop-blur-sm group-hover:bottom-2 transition-all duration-300">
请我喝奶茶<br/>
</div>
</div>
<div class="relative w-40 h-48 md:w-48 md:h-48 overflow-hidden
transition-all duration-300 ease-out hover:scale-125 group">
<img
src="./images/alipay-code.jpeg"
alt="支付宝赞赏码"
class="w-full h-full object-cover"/>
<div class="absolute -bottom-8 left-0 right-0 text-center
text-white bg-black opacity-60 text-sm font-medium
backdrop-blur-sm group-hover:bottom-2 transition-all duration-300">
请我吃晚饭<br/>
</div>
</div>
</div>

View File

@@ -1,3 +1,6 @@
@using YaeBlog.Models
@inject BlogOptions Options
<div class="px-4 py-8 border border-sky-700 rounded-md bg-sky-200">
<div class="flex flex-col gap-3 text-md">
<div>
@@ -21,17 +24,6 @@
Ricardo's Blog
</a>”。
</div>
<div class="flex flex-col">
<div class="flex justify-center">
<p>如果觉得不错的话,可以支持一下作者哦~</p>
</div>
<div class="flex justify-center">
<AppreciationCode/>
</div>
</div>
</div>
</div>

View File

@@ -6,7 +6,10 @@ namespace YaeBlog.Models;
public record BlogContents(ConcurrentBag<BlogContent> Drafts, ConcurrentBag<BlogContent> Posts)
: IEnumerable<BlogContent>
{
public IEnumerator<BlogContent> GetEnumerator() => Posts.Concat(Drafts).GetEnumerator();
IEnumerator<BlogContent> IEnumerable<BlogContent>.GetEnumerator()
{
return Posts.Concat(Drafts).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator GetEnumerator() => ((IEnumerable<BlogContent>)this).GetEnumerator();
}

View File

@@ -39,11 +39,6 @@
{
_page = Page ?? 1;
_pageCount = Contents.Count / EssaysPerPage + 1;
(_pageCount, int reminder) = int.DivRem(Contents.Count, EssaysPerPage);
if (reminder > 0)
{
_pageCount += 1;
}
if (EssaysPerPage * _page > Contents.Count + EssaysPerPage)
{

View File

@@ -16,11 +16,11 @@ public sealed class BlogHotReloadService(
await rendererService.RenderAsync(true);
Task[] reloadTasks = [WatchFileAsync(stoppingToken)];
Task[] reloadTasks = [FileWatchTask(stoppingToken)];
await Task.WhenAll(reloadTasks);
}
private async Task WatchFileAsync(CancellationToken token)
private async Task FileWatchTask(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
@@ -33,15 +33,6 @@ public sealed class BlogHotReloadService(
break;
}
FileInfo changeFileInfo = new(changeFile);
if (changeFileInfo.Name.StartsWith('.'))
{
// Ignore dot-started file and directory.
logger.LogDebug("Ignore hidden file: {}.", changeFile);
continue;
}
logger.LogInformation("{} changed, re-rendering.", changeFile);
essayContentService.Clear();
await rendererService.RenderAsync(true);

View File

@@ -109,12 +109,6 @@ public partial class EssayScanService : IEssayScanService
{
foreach (BlogResult blog in fileContents)
{
if (blog.BlogContent.Length < 4)
{
// Even not contains a legal header.
continue;
}
int endPos = blog.BlogContent.IndexOf("---", 4, StringComparison.Ordinal);
if (!blog.BlogContent.StartsWith("---") || endPos is -1 or 0)
{
@@ -127,14 +121,14 @@ public partial class EssayScanService : IEssayScanService
try
{
MarkdownMetadata metadata = _yamlDeserializer.Deserialize<MarkdownMetadata>(metadataString);
_logger.LogDebug("Scan metadata title: '{title}' for {name}.", metadata.Title, blog.BlogFile.Name);
_logger.LogDebug("Scan metadata title: '{}' for {}.", metadata.Title, blog.BlogFile.Name);
contents.Add(new BlogContent(blog.BlogFile, metadata, blog.BlogContent[(endPos + 3)..], isDraft,
blog.Images, blog.NotFoundImages));
}
catch (YamlException e)
{
_logger.LogWarning("Failed to parser metadata from {name} due to {exception}, skipping", blog.BlogFile.Name, e);
_logger.LogWarning("Failed to parser metadata from {} due to {}, skipping", blog.BlogFile.Name, e);
}
}
});

View File

@@ -1,13 +1,12 @@
---
title: High Performance Computing 25 SP NVIDIA
date: 2025-08-31T13:50:42.8639950+08:00
date: 2025-04-24T19:02:36.1077330+08:00
tags:
- 高性能计算
- 学习资料
---
Fxxk you, NVIDIA!
<!--more-->

View File

@@ -0,0 +1,10 @@
---
title: High Performance Computing 25 SP Quantum Computing
date: 2025-06-12T19:26:24.6668760+08:00
tags:
- 高性能计算
- 学习资料
---
<!--more-->

View File

@@ -1,13 +1,11 @@
---
title: High Performance Computing 25 SP Non Stored Program Computing
date: 2025-08-31T13:51:17.5260660+08:00
title: High Performance Computing 2025 SP Non Stored Program Computing
date: 2025-05-29T18:29:28.6155560+08:00
tags:
- 高性能计算
- 学习资料
---
No Von Neumann Machines.
<!--more-->
@@ -62,7 +60,7 @@ There are two types of semi-custom ASICs:
The Standard cell based ASICs is also called as **Cell-based ASIC(CBIC)**.
![image-20250815093113115](./hpc-2025-non-stored-program-computing/image-20250815093113115.webp)
![image-20250815093113115](./hpc-2025-non-stored-program-computing/image-20250815093113115.png)
> The *gate* is used a unit to measure the ability of semiconductor to store logical elements.
@@ -86,7 +84,7 @@ Depending on the structure, the standard PLD can be divided into:
- Programmable Logic Array(PLA): A programmable array of AND gates feeding a programmable of OR gates.
- Complex Programmable Logic Device(CPLD) and Field Programmable Gate Array(FPGA): complex enough to be called as *architecture*.
![image-20250817183832472](./hpc-2025-non-stored-program-computing/image-20250817183832472.webp)
![image-20250817183832472](./hpc-2025-non-stored-program-computing/image-20250817183832472.png)
@@ -98,7 +96,7 @@ Depending on the structure, the standard PLD can be divided into:
### FPGA Architecture
![image-20250817184419856](./hpc-2025-non-stored-program-computing/image-20250817184419856.webp)
![image-20250817184419856](./hpc-2025-non-stored-program-computing/image-20250817184419856.png)
#### Configurable Logic Block(CLB) Architecture
@@ -118,7 +116,7 @@ LUT is a ram with data width of 1 bit and the content is programmed at power up.
The below figure shows LUT working:
![image-20250817185111521](./hpc-2025-non-stored-program-computing/image-20250817185111521.webp)
![image-20250817185111521](./hpc-2025-non-stored-program-computing/image-20250817185111521.png)
The configuration memory holds the output of truth table entries, so that when the FPGA is restarting it will run with the same *program*.
@@ -128,7 +126,7 @@ And as the truth table entries are just bits, the program of FPGA is called as *
Let the input signal as address, the LUT will be configured as a RAM. Normally, LUT mode performs read operations, the address decoders can generate clock signal to latches for writing operation.
![image-20250817185859510](./hpc-2025-non-stored-program-computing/image-20250817185859510.webp)
![image-20250817185859510](./hpc-2025-non-stored-program-computing/image-20250817185859510.png)
#### Routing Architecture
@@ -136,7 +134,7 @@ The logic blocks are connected to each though programmable routing network. And
Horizontal and vertical mesh or wire segments interconnection by programmable switches called programmable interconnect points(PIPs).
![image-20250817192006784](./hpc-2025-non-stored-program-computing/image-20250817192006784.webp)
![image-20250817192006784](./hpc-2025-non-stored-program-computing/image-20250817192006784.png)
These PIPs are implemented using a transmission gate controlled by a memory bits from the configuration memory.
@@ -148,7 +146,7 @@ Several types of PIPs are used in the FPGA:
- Non-decoded MUX: n wire segments each with a configuration bit.
- Compound cross-point: 6 breakpoint PIPs and can isolate two isolated signal nets.
![image-20250817194355228](./hpc-2025-non-stored-program-computing/image-20250817194355228.webp)
![image-20250817194355228](./hpc-2025-non-stored-program-computing/image-20250817194355228.png)
#### Input/Output Architecture
@@ -160,7 +158,7 @@ The programmable Input/Output cells consists of three parts:
- Routing resources.
- Programmable I/O voltage and current levels.
![image-20250817195139631](./hpc-2025-non-stored-program-computing/image-20250817195139631.webp)
![image-20250817195139631](./hpc-2025-non-stored-program-computing/image-20250817195139631.png)
#### Fine-grained and Coarse-grained Architecture
@@ -188,9 +186,9 @@ Three types of interconnected devices have been commonly used to connect there w
### FPGA Design Flow
![image-20250817195714935](./hpc-2025-non-stored-program-computing/image-20250817195714935.webp)
![image-20250817195714935](./hpc-2025-non-stored-program-computing/image-20250817195714935.png)
![image-20250817200350750](./hpc-2025-non-stored-program-computing/image-20250817200350750.webp)
![image-20250817200350750](./hpc-2025-non-stored-program-computing/image-20250817200350750.png)
The FPGA configuration techniques contains:
@@ -224,7 +222,7 @@ The OpenCL is not an traditional hardare description language. And OpenCL needs
The follow figure shows how the OpenCL-FPGA compiler turns an vector adding function into the circuit.
![image-20250829210329225](./hpc-2025-non-stored-program-computing/image-20250829210329225.webp)
![image-20250829210329225](./hpc-2025-non-stored-program-computing/image-20250829210329225.png)
The compiler generates three stages for this function:

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,12 +1,11 @@
---
title: High Performance Computing 25 SP OpenCL Programming
date: 2025-08-31T13:51:02.0181970+08:00
title: High Performance Computing 2025 SP OpenCL Programming
date: 2025-05-29T18:29:14.8444660+08:00
tags:
- 高性能计算
- 学习资料
---
Open Computing Language.
<!--more-->

View File

@@ -1,12 +1,11 @@
---
title: High Performance Computing 25 SP Potpourri
date: 2025-08-31T13:51:29.8809980+08:00
date: 2025-06-12T18:45:49.2698190+08:00
tags:
- 高性能计算
- 学习资料
---
Potpourri has a good taste.
<!--more-->

View File

@@ -1,12 +1,11 @@
---
title: High Performance Computing 25 SP Programming CUDA
date: 2025-08-31T13:50:53.6891520+08:00
title: High Performance Computing 2025 SP Programming CUDA
date: 2025-05-15T19:13:48.8893010+08:00
tags:
- 高性能计算
- 学习资料
---
Compute Unified Device Architecture
<!--more-->

View File

@@ -1,130 +0,0 @@
---
title: Podman容器中特定域名解析失败问题排查
date: 2025-10-22T17:42:07.7738936+08:00
tags:
- 技术笔记
- Bug Collections
---
最难以置信的一集。
<!--more-->
## 问题现象
在折腾我的Gitea CI/CD管线的时候我我尝试进行一项重要的变更在运行CI任务时任务中的容器支持从Docker out of DockerDoD迁移到Podman inside PodmanPiP。但是在执行该项迁移的过程中我遇到了如下一个非常神秘的Bug。
在CI任务运行的过程中我发现一些**特定的**、**稳定的**域名无法在任务容器中正常解析并请求。目前注意到的域名有如下两个:
- dot.net
- rcj.bupt-hpc.cn
在容器内使用`curl http://dot.net -vvvvi`时,日志中重复出现如下内容。
```
10:35:43.261007 [0-x] == Info: [MULTI] [INIT] added to multi, mid=1, running=1, total=2
10:35:43.261252 [0-x] == Info: [MULTI] [INIT] multi_wait(fds=1, timeout=0) tinternal=0
10:35:43.261533 [0-x] == Info: [MULTI] [INIT] -> [SETUP]
10:35:43.261690 [0-x] == Info: [MULTI] [SETUP] -> [CONNECT]
10:35:43.261838 [0-x] == Info: [READ] client_reset, clear readers
10:35:43.262042 [0-0] == Info: [MULTI] [CONNECT] [CPOOL] added connection 0. The cache now contains 1 members
10:35:43.262315 [0-0] == Info: [DNS] init threaded resolve of rcj.bupt-hpc.cn:9090
10:35:43.262597 [0-0] == Info: [DNS] resolve thread started for of rcj.bupt-hpc.cn:9090
10:35:43.262854 [0-0] == Info: [MULTI] [CONNECT] [TIMEOUT] set ASYNC_NAME to expire in 1000ns
10:35:43.263081 [0-0] == Info: [MULTI] [CONNECT] -> [RESOLVING]
10:35:43.263254 [0-0] == Info: [MULTI] [RESOLVING] multi_wait pollset[fd=4 IN], timeouts=1
10:35:43.263500 [0-0] == Info: [MULTI] [RESOLVING] [TIMEOUT] ASYNC_NAME expires in 355ns
10:35:43.263743 [0-0] == Info: [MULTI] [RESOLVING] multi_wait(fds=2, timeout=1) tinternal=1
10:35:43.265041 [0-0] == Info: [DNS] Curl_resolv_check() -> 0, missing
10:35:43.265218 [0-0] == Info: [MULTI] [RESOLVING] multi_wait pollset[fd=4 IN], timeouts=1
10:35:43.265497 [0-0] == Info: [MULTI] [RESOLVING] [TIMEOUT] ASYNC_NAME expires in 1545ns
10:35:43.265736 [0-0] == Info: [MULTI] [RESOLVING] multi_wait(fds=2, timeout=2) tinternal=2
10:35:43.268052 [0-0] == Info: [DNS] Curl_resolv_check() -> 0, missing
10:35:43.268236 [0-0] == Info: [MULTI] [RESOLVING] multi_wait pollset[fd=4 IN], timeouts=1
10:35:43.268471 [0-0] == Info: [MULTI] [RESOLVING] [TIMEOUT] ASYNC_NAME expires in 3582ns
10:35:43.268688 [0-0] == Info: [MULTI] [RESOLVING] multi_wait(fds=2, timeout=4) tinternal=4
```
## 初步假设与排除过程
这个问题非常奇怪,在问题排查初期,我进行了如下的操作。
1. 首先单独测试容器中的域名解析,使用`dig rcj.bupt-hpc.cn`进行解析测试解析的结果符合预期使用的DNS服务器是当前的容器的Podman网关地址10.17.14.1。
2. 独立启动容器而不是使用CI管线启动的容器使用`podman run --rm -it --privileged ccr.ccs.tencentyun.com/jackfiled/runner-base:latest bash -l`创建容器,对上述出现问题的两个域名上的服务进行请求,没有问题,排除镜像本身的问题。
此时已经束手无策了遂尝试AI辅助进行排查。
## AI辅助下的问题排查
### dig工具和libc的解析机制之前存在差异
AI首先提到上面测试的dig工具和其他应用使用的libc解析机制之间存在差异
- `dig` 是直接使用 DNS 协议向 DNS 服务器发查询请求(绕过系统的解析器)。
- `curl`(以及大多数应用)依赖系统 C 库(如 glibc`getaddrinfo()` 函数,它会读取 `/etc/nsswitch.conf``/etc/resolv.conf`,并可能使用 `systemd-resolved``nscd` 等服务。
于是需要使用`getent`工具测试libc库的DNS解析是否存在问题测试发现解析结果正常。
### IPv6 优先导致超时或失败
AI还提到如果系统尝试先用 IPv6 解析AAAA 记录),但网络不支持 IPv6可能导致 `curl` 卡住或失败,而 `dig` 默认查 A 记录。
于是在使用`curl`时手动指定使用的网络协议,的确当使用`curl -4 http://dot.net`时可以正常的完成请求。
虽然这一方法可以解决问题但是其给出的理由似乎无法解释我遇到的问题问题域名中的rcj.bupt-hpc.cn并没有任何的AAAA解析记录执行 `getent ahosts rcj.bupt-hpc.cn` 仅返回 IPv4 地址,无 AAAA 记录,说明系统解析器未返回 IPv6 地址,`curl -4` 的成功不能用IPv6解释。
### DNS服务器
在尝试AI给出的几个建议之后我也开始尝试修改容器内的DNS服务器进行这个尝试是因为我发现使用`podman run`启动容器时容器内部使用的DNS服务器是10.3.9.4这一主机使用的DNS服务器而在CI管线中启动的容器使用的DNS服务器是172.17.14.1这一容器网关。
于是在CI启动的容器中我通过直接写入`/etc/resolv.conf`文件的方式修改DNS服务器为10.3.9.4,在修改之后,针对两个域名的网络请求就恢复了正常。
在将上述的新发现同步给AI之后AI又给出了一些新的思路。
### c-ares 异步 DNS 解析器兼容性问题?
- 某些编译版本的 `curl`(尤其是 Alpine、某些容器镜像会链接 `c-ares` 库,**绕过 glibc 的 `getaddrinfo`**,直接读取 `/etc/resolv.conf` 并发 DNS 请求。
- `c-ares` **不读取 `/etc/nsswitch.conf`**,也不支持 mDNS、systemd-resolved 等机制。
- 如果 `/etc/resolv.conf` 中的 nameserver`172.17.14.1`)对 **某些域名响应异常**(如超时、截断、不响应 UDP 包),`c-ares` 会卡住。
但是按照AI提供的步骤进行排查
- `curl --version` 输出中**未包含 `c-ares`**
- curl 使用 glibc 的 `getaddrinfo()` 或 libcurl threaded resolver
- **结论**:非 c-ares 导致。
### UDP DNS 响应截断(>512 字节)?
- `c-ares` 默认使用 **UDP** 查询 DNS。
- 如果 Podman 的内置 DNS 代理(通常是 `netavark` + `aardvark-dns` 或旧版 `dnsmasq`)在处理 **特定域名** 的 UDP 请求时:
- 响应过大导致 UDP 截断TC=1`c-ares` 未自动重试 TCP
- 或代理本身 bug 导致丢包;
-`c-ares` 会认为“无响应”返回“missing”。
`dig` 默认使用 UDP但**当 TC=1时会自动使用TCP重试**,所以成功,而你的域名 `rcj.bupt-hpc.cn` 可能有较多 CNAME 或 TXT 记录,导致 UDP 响应超 512 字节。
但是我清楚的知道域名 `rcj.bupt-hpc.cn` 仅有一条 A 记录DNS 响应极小,`dig``getent` 均能快速返回结果。
## AI ConclusionPodman 内置 DNS 代理aardvark-dns行为异常
Podman 4.5.2 默认使用 **aardvark-dns** 作为容器网络的 DNS 代理,监听于网关地址(如 `172.10.0.1`)。其职责包括:
- 解析容器名称(服务发现);
- 转发外部域名查询至上层 DNS。
可能的故障点包括:
1. aardvark-dns 对特定域名后缀(如 `.bupt-hpc.cn`)的转发逻辑存在缺陷;
2. 响应格式不符合 glibc 或 libcurl 的预期(如缺少 AA 标志、TTL 异常);
3. 首次查询存在延迟或丢包,而 libcurl threaded resolver 未充分重试;
4. 与宿主机 `/etc/resolv.conf` 中的 `search` 域交互异常,导致拼接错误查询。
尽管 `dig` 能获取结果,但 `dig` 具有更强的容错性和自动重试机制(如 TC=1 时切 TCP而 libcurl 的 resolver 更严格。
> 对于AI的这个结果说实话我表示怀疑我感觉还是和IPv6有关系这样才能同时解释`curl -4`和更换DNS都可以运行的现象。
## 临时缓解
最终我在CI启动容器的配置选项中添加`--dns 10.3.9.4`不使用Podman启动的DNS服务器暂时绕过了这个问题。
不过这个问题并没有从本质上得到解决,甚至都还不知道背后的具体问题是什么,感觉会在后面攻击我,特此记录。

BIN
YaeBlog/wwwroot/images/alipay-code.jpeg (Stored with Git LFS)

Binary file not shown.

BIN
YaeBlog/wwwroot/images/wechat-code.jpeg (Stored with Git LFS)

Binary file not shown.