沙丘猫窝

沙丘猫窝 - SrakhiuMeow

开始在Linux Mint用AppImage版本的Krita,但是AppImage版不能自动更新,因此改用Flatpak版本。

然而,安装之后发现在高分屏(4K)下Krita的鼠标指针异常地小,且指针形状与系统指针也不同。

flatpak-cursor-too-small.png

经过搜索,发现这是因为Flatpak应用在容器中运行,默认无法获取当前所用的主题文件导致的光标异常问题。

Linux Mint系统的解决方法

在Linux Mint论坛上的这个帖子中,找到了解决办法:

新建一个文件~/.local/share/icons/default/index.theme,在其中指定光标主题即可。

可以执行下面这段代码来完成:

1
2
3
4
5
6
7
mkdir ~/.local/share/icons/default
cd ~/.local/share/icons/default
touch index.theme
cat > ./index.theme << EOF
[icon theme]
Inherits=Bibata-Modern-Classic
EOF

其中,Bibata-Modern-Classic可以换为你正在使用的光标主题名称。

此时再进入Krita就一切正常了。

其他Linux系统的解决方法

其他系统则可以尝试下这里提到的方法(Linux Mint下无效):

Flatpak App Changing Cursor Theme And Size (Is This Normal Behavior?)

执行:

1
2
flatpak --user override --filesystem=/home/$USER/.icons/:ro
flatpak --user override --filesystem=/usr/share/icons/:ro

本文将介绍如何在Linux Mint下安装fcitx5-rime与其对应的rime-cantonese

问题说明

最近想要(再次)尝试下linux,就选择了Linux Mint系统。由于在Windows习惯了用小狼毫(rime)的粤语输入法,因此就直接按照官网推荐安装了ibus-rime。

然而在使用时,发现Ibus输入法对于高分屏的支持不佳,在缩放比例为200%时,在一些应用(例如Firefox)中候选框显示错位。

在网上搜索了一些相关讨论 https://github.com/ibus/ibus/issues/2221 ,提到这是ibus上游的问题,也没有什么较好的解决方法。如果将缩放比例调整至100%则显示正常,但用起来非常难受;或者就可以改用基于fcitx5的输入法,就不会出现这些问题。

然而,rime-cantonese官方对于Debain系提供的是ibus的安装脚本,而其fcitx5版本并没有在Linux Mint的仓库中。幸运的是,我们可以通过从其Github仓库下载文件的方法实现手动安装。

安装教程

首先,安装fcitx5-rime:

1
sudo apt install fcitx5-rime -y

接下来为rime安装粤语输入法(rime-cantonese),执行以下命令

1
2
3
4
5
6
7
8
9
10
11
12
# 克隆 粤语输入法、emoji显示、两分输入的仓库
git clone https://github.com/rime/rime-cantonese.git ~/.rime-cantonese
git clone https://github.com/rime/rime-emoji-cantonese.git ~/.rime-emoji-cantonese
git clone https://github.com/CanCLID/rime-loengfan.git ~/.rime-loengfan

# 建立fcitx5-rime配置文件夹到粤语输入文件的软链接
mkdir -p ~/.local/share/fcitx5/rime/opencc
ln -s ~/.rime-cantonese/*.yaml ~/.local/share/fcitx5/rime
ln -s ~/.rime-cantonese/*.txt ~/.local/share/fcitx5/rime # 注意没有这句话会导致候选词频混乱
ln -s ~/.rime-cantonese/opencc/* ~/.local/share/fcitx5/rime/opencc
ln -s ~/.rime-emoji-cantonese/*.yaml ~/.local/share/fcitx5/rime
ln -s ~/.rime-emoji-cantonese/opencc/* ~/.local/share/fcitx5/rime/opencc

再新建 ~/.local/share/fcitx5/rime/default.custom.yaml,配置rime

1
2
3
4
5
6
patch:
schema_list:
- schema: jyut6ping3
- schema: luna_pinyin_simp
# 以及其他需要的输入方案
"menu/page_size": 9

打开fcitx5,在fcitx5配置中增加「中州韵」输入法(如果有则忽略本步)。

如果配置未生效,则可以右键任务栏的fcitx5按钮,选择重新启动,等待rime重新部署完成即可。

配置教程

配置输入法

用nano等编辑器打开jyut6ping3.schema.yaml文件
修改ascii_punct上面的reset后数字为3即可默认输入法为简体
删除states: [ 冇 Emoji, 有 Emoji ]上面一行reset前面的#号,即可启用emoji🤨输入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
switches:
- name: ascii_mode
reset: 0
states: [ , ]
- name: full_shape
states: [ 半角, 全角 ]
- options: [ noop, variants_hk, trad_tw, simplification ]
states: [ 傳統漢字, 香港傳統漢字, 臺灣傳統漢字, 大陆简化汉字 ]
# 修改下面箭嘴指住嘅數字以改變預設用字(數字 [0, 1, 2, 3] 分別對應上表)
# 例如「reset: 0」會將用字預設為 OpenCC 傳統漢字,如此類推
# Edit the number indicated by the arrow below to change the default character style
# [0 = OpenCC Traditional Chinese; 1 = Hong Kong TC; 2 = Taiwan TC; 3 = Mainland Simplified Chinese]
# 或刪除下行以記住用户設定 Or remove the following line to remember user setting
reset: 3 # <-- 此數字 this number
- name: ascii_punct
states: [ 。,, ., ]
- name: emoji_cantonese_suggestion
# 取消下行註釋(移除 # 號),預設啓動 emoji
reset: 1
states: [ Emoji, Emoji ]

安装皮肤

默认的rime并不美观,可以通过安装皮肤的方法来美化,以 https://github.com/thep0y/fcitx5-themes-candlelight 为例:

首先下载皮肤,并将皮肤文件复制到fcitx5的皮肤文件夹中:

1
2
3
git clone https://github.com/thep0y/fcitx5-themes.git
cd fcitx5-themes
cp spring ~/.local/share/fcitx5/themes -r

再修改fcitx5的皮肤配置文件(若没有配置文件则自动创建):

1
vim ~/.config/fcitx5/conf/classicui.conf

将下面的参数复制进去(记得修改字体):

1
2
3
4
5
6
7
8
9
10
11
# 垂直候选列表
Vertical Candidate List=False

# 按屏幕 DPI 使用
PerScreenDPI=True

# Font (设置成你喜欢的字体)
Font="Smartisan Compact CNS 13"

# 主题(这里要改成你想要使用的主题名,主题名就在下面)
Theme=spring

搞掂晒(

由于安装Linux Mint时没有划分单独的swap分区,于是想要创建一个swapfile使用,然而在激活时报错:

1
swapon: /swapfile: swapon failed: Invalid argument

通过在网上查找,从https://forums.linuxmint.com/viewtopic.php?t=407061得知:问题在于我安装Linux Mint时将分区选为btrfs格式,此时用直接用dd创建的交换文件无效。

解决办法:

删除之前创建的swapfile,再执行如下操作:

1
2
sudo btrfs filesystem mkswapfile --size 16G swapfile # 其中16G改为你所需的交换文件大小
sudo swapon swapfile

此时能够顺利启用swapfile了

如果还需要开机自动挂载的话可以打开etc/fstab,在最后增加一行

1
/swapfile none swap defaults 0 0

Lofter网页版没有广告,界面清爽,但是缺少移动端APP的许多功能。
本文将介绍如何安装Lofter网页版增强插件,在PC端使用Lofter的划线评论/历史记录/用户合集/订阅更新/首页推荐

脚本功能介绍

目前一共有五种脚本,其功能分别如下:

  1. lofter-comment:Lofter 网页版显示划线评论

    仿照手机版将文章的划线评论显示对应段落后面,可以折叠
    (注意,必须点进全文详情才能工作)

  2. lofter-collection: Lofter 网页版显示用户合集

    在用户页(形如xxx.lofter.com)上增加一个”合集”按钮

    点击后可以看到该用户发布的合集信息

  3. lofter-subscription: Lofter网页版查看订阅合集

    在首页右边的工具栏增加”订阅合集”按钮
    可以查看你订阅了哪些合集
    并可以查看合集的内容(点击”查看详情”)

  4. lofter-history: Lofter 网页版显示移动端历史记录

    在首页右边的工具栏增加”历史记录”按钮
    可以查看手机版Lofter上的历史记录
    (网页版的浏览文章不会被Lofter官方记录)

  5. lofter-discover: Lofter网页版查看发现内容(手机版的首页推荐)

    网页版的首页默认只能查看关注用户的推荐
    该脚本可以实现查看手机版首页的推荐列表
    点击右边工具栏的”发现”即可进入该模式

安装教程

1️⃣ 首先需要安装TamperMonkey(篡改猴)

根据你的浏览器选择安装链接

注意:如果使用的是Edge浏览器,则需要开启开发者模式才能正常启用,可以参照这篇文章操作

2️⃣ 根据需要安装上述脚本

  1. 快速安装

    如果能够科学上网的话,可以点我到我的GreasyFork仓库选择所需的脚本安装,这种方法支持自动更新

    如果不能科学上网,点我到ScriptCat同样能够一键安装

  2. 手动从源码安装

    如果两个链接都无法访问,也可以点我下载源码,手动安装脚本(请注意,这种方法不能自动更新)

    下载源码后解压,scripts文件夹内的.js文件即为脚本文件。

    需要安装某一个脚本的话,需要用记事本打开它,复制其中的所有内容;点击TamperMonkey按钮,选择“添加新脚本”,点击加号按钮新建脚本,删掉其中内容,再将之前复制的脚本复制进去,按下Ctrl+S保存即可

    如果找不到TamperMonkey按钮的话,可以试下点击该按钮,在打开的列表中寻找

    如果需要安装多个脚本,重复上述步骤即可

源码仓库

代码已经上传到Github(虽然GreaseFork本来就要求开源(
如果有问题欢迎提issue(虽然不一定会修(

有需要的用户可以自行创建分枝,如果帮到你的话点个star吧(

Github代码仓库

介绍

Lofter的网页端没有原生的划线评论查看功能,体验不如使用移动端APP,因此本人在Deepseek指导下写了一份能让Lofter网页版也显示划线评论的脚本

效果展示

划线评论显示效果

下载地址

Github仓库地址:点我
GreasyFork脚本安装地址:点我

安装方法

  1. 首先安装篡改猴(TamperMonkey):

注意:如果使用的是Edge浏览器,则需要开启开发者模式才能正常启用,可以参照这篇文章操作

  1. 接下来点我前往GreasyFork网站安装本脚本

  2. 安装完成!

原理

Lofter上的文章每一段都有对应的id,如

1
<p id='xxxxxx'>你好</p>

手机端获取评论时也会同时获取其对应的pid(非划线评论则为null),并根据pid将其显示到对应段落后面。

而经过浏览器抓包分析,发现网页版Lofter虽然不显示划线评论,但其评论请求的响应中也带有每条评论对应pid位置,如:

1
2
var s1={};
s1.content="yyy"; ...; s1.pid="xxxxxx";

因此,本脚本用ajax-hook拦截评论请求,并根据响应内容,将评论显示到其pid对应的位置后,实现了划线评论的显示。具体逻辑参见Github仓库(点我)

存在问题

  1. 目前不能显示划线评论中的回复评论
  2. 不支持GreaseMonkey
  3. 按钮有待美化
  4. 尚不能显示划线的具体是一段中的哪些字

发现其他问题可以来Github仓库上提Issue

问题描述

在使pytorch/pytorchnvidia-cuda的Docker镜像下使用Paddle或者Onnxruntime-gpu可能会出现找不到CUDA或者CUDNN文件的报错。

Paddle报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
W1120 01:52:39.805847   549 dynamic_loader.cc:314] The third-party dynamic library (libcudnn.so) that Paddle depends on is not configured correctly. (error code is /usr/local/cuda/lib64/libcudnn.so: cannot open shared object file: No such file or directory)
Suggestions:
1. Check if the third-party dynamic library (e.g. CUDA, CUDNN) is installed correctly and its version is matched with paddlepaddle you installed.
2. Configure third-party dynamic library environment variables as follows:
- Linux: set LD_LIBRARY_PATH by `export LD_LIBRARY_PATH=...`
- Windows: set PATH by `set PATH=XXX;
Traceback (most recent call last):
File "deploy/pipeline/pipeline.py", line 1321, in <module>
main()
File "deploy/pipeline/pipeline.py", line 1308, in main
pipeline.run_multithreads()
File "deploy/pipeline/pipeline.py", line 179, in run_multithreads
self.predictor.run(self.input)
File "deploy/pipeline/pipeline.py", line 533, in run
self.predict_video(input, thread_idx=thread_idx)
File "deploy/pipeline/pipeline.py", line 993, in predict_video
classes, scores = self.video_action_predictor.predict(
File "deploy/pipeline/pphuman/video_action_infer.py", line 192, in predict
input_tensor.copy_from_cpu(inputs)
File "/usr/local/lib/python3.8/dist-packages/paddle/inference/wrapper.py", line 52, in tensor_copy_from_cpu
self._copy_from_cpu_bind(data)
RuntimeError: (PreconditionNotMet) Cannot load cudnn shared library. Cannot invoke method cudnnGetVersion.
[Hint: cudnn_dso_handle should not be null.] (at /paddle/paddle/phi/backends/dynload/cudnn.cc:64)

Onnxruntime-gpu报错:

1
2
3
2024-11-15 02:09:12.841326104 [E:onnxruntime:Default, provider_bridge_ort.cc:1480 TryGetProviderInfo_CUDA] /onnxruntime_src/onnxruntime/core/session/provider_bridge_ort.cc:1193 onnxruntime::Provider& onnxruntime::ProviderLibrary::Get() [ONNXRuntimeError] : 1 : FAIL : Failed to load library libonnxruntime_providers_cuda.so with error: libcublasLt.so.11: cannot open shared object file: No such file or directory

2024-11-15 02:09:12.841349327 [W:onnxruntime:Default, onnxruntime_pybind_state.cc:743 CreateExecutionProviderInstance] Failed to create CUDAExecutionProvider. Please reference https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html#requirements to ensure all dependencies are met.

解决方法:

首先要确保你的使用pytorch/pytorchnvidia-cuda镜像带有CUDNN,即镜像名中应该带有cudnn字样。

在镜像环境带有CUDA与CUDNN文件,而Paddle与Onnxruntime等软件仍无法识别到时,则可以通过手动指定CUDA与CUDNN库目录的方法来解决。

nvidia/cuda:11.7.1-cudnn8-runtime-ubuntu20.04镜像为例:

定位库文件:

首先创建一个临时容器用于寻找CUDA与CUDNN库的位置

1
sudo docker run -it --gpus all --rm nvidia/cuda:11.7.1-cudnn8-runtime-ubuntu20.04 /bin/bash

其中--rm参数代表容器退出后自动删除。

执行

1
find / -name *libcudnn*

得到结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/usr/share/doc/libcudnn8
/usr/share/lintian/overrides/libcudnn8
/usr/lib/x86_64-linux-gnu/libcudnn_ops_train.so.8.5.0
/usr/lib/x86_64-linux-gnu/libcudnn_ops_train.so.8
/usr/lib/x86_64-linux-gnu/libcudnn_cnn_infer.so.8
/usr/lib/x86_64-linux-gnu/libcudnn_adv_train.so.8.5.0
/usr/lib/x86_64-linux-gnu/libcudnn_cnn_infer.so.8.5.0
/usr/lib/x86_64-linux-gnu/libcudnn_adv_infer.so.8
/usr/lib/x86_64-linux-gnu/libcudnn_ops_infer.so.8.5.0
/usr/lib/x86_64-linux-gnu/libcudnn_ops_infer.so.8
/usr/lib/x86_64-linux-gnu/libcudnn.so.8
/usr/lib/x86_64-linux-gnu/libcudnn_adv_infer.so.8.5.0
/usr/lib/x86_64-linux-gnu/libcudnn_adv_train.so.8
/usr/lib/x86_64-linux-gnu/libcudnn_cnn_train.so.8
/usr/lib/x86_64-linux-gnu/libcudnn.so.8.5.0
/usr/lib/x86_64-linux-gnu/libcudnn_cnn_train.so.8.5.0
/var/lib/dpkg/info/libcudnn8.md5sums
/var/lib/dpkg/info/libcudnn8.list

可知该镜像的CUDNN库位于/usr/lib/x86_64-linux-gnu

再执行

1
find / -name *libcublas*

得到结果

1
2
3
4
5
6
7
/usr/share/doc/libcublas-11-7
/usr/local/cuda-11.7/targets/x86_64-linux/lib/libcublasLt.so.11.10.3.66
/usr/local/cuda-11.7/targets/x86_64-linux/lib/libcublasLt.so.11
/usr/local/cuda-11.7/targets/x86_64-linux/lib/libcublas.so.11.10.3.66
/usr/local/cuda-11.7/targets/x86_64-linux/lib/libcublas.so.11
/var/lib/dpkg/info/libcublas-11-7.md5sums
/var/lib/dpkg/info/libcublas-11-7.list

可知该镜像的CUDA算子位于/usr/local/cuda-11.7/targets/x86_64-linux/lib

添加环境变量:

为了让Paddle与Onnxruntime能够找到CUDA与CUDNN的位置,需要将上面找到的两个路径添加到环境变量LD_LIBRARY_PATH,如果是临时使用容器的话,可以用该指令来临时指定(仅在当前终端有效)

1
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/local/cuda-11.7/targets/x86_64-linux/lib:$LD_LIBRARY_PATH

其中/usr/lib/x86_64-linux-gnu:/usr/local/cuda-11.7/targets/x86_64-linux/lib要根据自己在前两步获得的算子路径来修改,路径间用:隔开。

而在构造镜像时,在Dockerfile中增加:

1
RUN echo export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/local/cuda-11.7/targets/x86_64-linux/lib:$LD_LIBRARY_PATH >> ~/.bashrc

则可在进入容器时自动指定CUDA与CUDNN算子文件位置。

Lofter的网页端不支持查看合集内容,只能用移动端设备看,对PC党很不友好。
只好通过对Lofter的安卓客户端抓包,分析API来进行合集内容的批量下载了。

用Python实现了一个简陋的批量下载合集内容并保存为markdown格式的脚本,可以保存文章中的图片。
可以不登录账户但需要手动获取合集ID,也可以在登录网页端Lofter的情况下获取当前账号订阅合集的ID(会读取Cookie信息)。

Github项目地址:
https://github.com/SrakhiuMeow/lofter-getter

使用说明

  1. 用git克隆项目:

    1
    2
    git clone https://github.com/SrakhiuMeow/lofter-getter
    cd lofter-getter

    当然也可以在浏览器打开项目地址,直接下载zip到本地后解压。

  2. 安装环境:

    1
    pip install -r requirements.txt
  3. 获取合集ID:

    下载合集需要获取其ID,有两种方法:

    1. 在Lofter App中进入合集页面,选择分享——复制链接,得到链接中CollectionId后的数字即为合集ID
    2. 在浏览器中登录Lofter,再运行本项目提供的subscription.py,即可获得合集ID
      1
      python subscription.py
  4. 爬取合集:

    此时,运行collection.py即可批量下载合集内容(默认下载到./results中)

    1
    python collection.py --collection_id 合集ID

    可选参数:

    • --save-path 保存路径 指定保存路径,默认在当前目录的results文件内
    • --save_img 将图片内容保存到本地(默认保存图片链接)
    • --rewrite 覆盖本地已下载的内容
    • --limit_once 单次抓取数 单次抓取的文章数量(默认50篇)

    会将合集内所有文章保存至保存路径/合集名
    并在保存路径下建立以合集名为文件名的目录文件,方便使用

(虽然功能真的很简陋,但是如果能帮到你的话,求求给github项目点个star吧🥹我什么都不会做的

实验室有两台同型号不同批次的8盘位硬盘柜,一台用于冷备份,一台给NAS用;二者都是通过SAS线接到主机的LSI阵列卡上来通信。

故障显现

某一天,因为要收拾实验室,就搬动了冷备用的电脑与硬盘柜。等到再次通电开机时,发现阵列卡开机自检环节就过不去,进度多次到100后又归零,然后就蜂鸣器就开始响。没办法,就只好先拔掉SAS线,先开机再插上去。

此时打开Megaraid Storage Manager,能够识别到硬盘柜,但也会报警;没办法,警报实在太吵,进Logical选项卡,右键Controller选择Disable Alarm,终于安静下来了。

右键Controller选择Scan Foreign Configuration,还好,能识别到8块盘的正常,然后选Import导入,此时问题出现:有一块盘Failed,Virtual Drive整体处于降级状态。 不过因为组的是RAID10,坏一块盘数据还能浏览,问题(应该)不大。

因为已经过保,就想办法自己解决下先。

首先尝试用MSM进行重建,然而报错如下

1
2
Controller ID:0 Rebuild failed due to target drive error: PD Port B:0:0
Controller ID:0 Diagnostivs failed on PD: Port B:0:0

在网上翻了很多资料,也没什么有价值的信息。

更换硬盘

因为尝试重建失败,而且用Diskgenius也获取不到对应盘的SMART信息,因而以为是这块硬盘坏了。(其实当时尝试把这块盘装到其他电脑上,也能获取到SMART信息,但被网上说可能是因为RAID对SMART要求更严格的信息误导了…)

求助硬盘柜的客服,也没有给出什么有用的信息(还是Scan Foreign Configuration-Rebuild那一套),因为过保、其仅能寄修不能上门,且硬盘数据不能外传,因此问对方能否直接更换硬盘,得到了可以尝试的答复。

于是买了一块同型号硬盘(¥2k+,14TB容量的硬盘真是奇葩,好难买),结果买了新的硬盘换上也没用,也不能退,寄(虽然能报销)。

此时才想到NAS用的是同型号的硬盘柜,可以试下将冷备硬盘放到NAS用硬盘柜中再接到冷备的电脑上,看下到底是不是硬盘问题。废了一番功夫装上硬盘,开机,重建,正常进入流程,并在十几个小时后重建成功了,重启后也一切正常(重建过程中数据读取灯一直为读取状态,但是硬盘确没有声音,因此认定硬盘内数据并没有损坏,这次重建只是全盘校验了一遍)……而此时再把硬盘装回冷备硬盘柜,连接电脑,开机,还是一样报错。

虽然绕了一大圈,但是退一万步,至少确定了问题不在硬盘上(而且等过几年真有硬盘坏掉就不用再临时买备用盘了(

此时又发现,有时重启冷备主机后只能识别到7块硬盘,干脆不认“故障盘”了,因此更加确信是硬盘柜出现故障。

寄修盘柜

只好寄修硬盘柜,因为认为是其自身的问题,就寄了空柜过去;

在微信联系的客服送修,结果寄出后一个星期都没有回复;只好打电话过去,得知当时跟我交接的客服已经离职了(…),对方表示会尽快帮忙维修——然而接下来又等了半个月,催了一次后终于搞定了——对面说“清灰之后就正常了”,因此不收维修费,只要我出快递费就好了。真是不错,虽然白买了硬盘,还拖了这么久,至少没再花维修钱而且修好了……吗?

当我把硬盘装上寄回的硬盘柜后,依然出现硬盘识别问题,甚至更严重了——这次只能识别5-6块盘,重启一次识别数还会变化,直接无语……这还不是最糟糕的,当我再次尝试把这些硬盘装到NAS用的硬盘柜内,再接到冷备份用的电脑上后,发现它居然只能识别slot0-3上的4块硬盘!

我的心直接凉了,不会是装硬盘时大力出“奇迹”了吧!

冷静冷静,再折腾下试试——把硬盘的上下顺序掉换一下,开机,发现识别的还是4块盘,但是识别到的是换到slot0-3盘位上的盘——原来硬盘没被搞坏。
但这台NAS用的硬盘柜分明没有问题啊?这次终于想到,问题可能出在一开始就忽略掉的LSI阵列卡上……

阵列卡!?

拔掉NAS主机上的LSI阵列卡,插到冷备主机上,连接SAS线,开机——全部硬盘均能识别。虽然还是提示有块盘Failed(就是最开始的那块“坏盘”),但是经过第一次换硬盘的经验,硬盘里面的数据应该是一切正常的,只是之前读取失败导致的Failed状态保留下来了;
理论上这次不用浪费时间进行重建了。于是,右键对应硬盘,选择Make Drive Online——一切正常了。

真是没有想到,最后居然是阵列卡的问题?但是第一次进行硬盘柜交换时就能正常识别,为什么第二次交换后就出了问题?这期间也没动过阵列卡。

本来打算再次寄修这块冷备用阵列卡,但是这次涨了教训,为了防止再白忙活一趟,干脆把它又装到了NAS主机上测试,结果竟然能正常工作。

说明这块阵列卡并没有坏掉……?

由于之前进行的互换实验并不充分,而且也不知寄修后售后方具体进行了哪些操作,故障好的莫名其妙,网上资料又太少,导致没法具体证明问题的源头……
但是这一系列问题,很可能只是因为阵列卡与主板接触不良导致的……吗?

电源线!!??

然而,没过几天,再次上电的时候又出现了掉盘情况——Slot6的盘完全识别不到了。这下是真的没办法了……难道是供电问题?但是电源和硬盘柜是一体的啊。算了,死马当活马医吧,换了一根电源线,居然又正常了……

结束(?)

这次真的是让人崩溃,真不知道问题出在了哪里……资料太少,甚至都不知道能找谁来修,只能自己折腾,至少现在暂时又能用了……

看到这篇文章的难兄难弟,遇到莫名其妙的RAID问题可以试下插拔阵列卡或者换根电源线……

省流版

如果requests返回的response是完全的乱码,而不是单纯的中文部分乱码,请尝试用pip安装brotli

1
2
# 在终端执行
pip install brotli

完整说明

问题简述

在使用python的requests对某网站发送POST请求后,发现获取到的respnse.text为乱码
乱码图片

而且保存为json时也会报错

1
2
3
4
5
6
7
8
9
10
11
12
13
Traceback (most recent call last):
File "xxx.py", line 41, in <module>
response_json = json.loads(text)['response']
^^^^^^^^^^^^^^^^
File "C:\Users\[User]]\miniconda3\envs\fastapi\Lib\json\__init__.py", line 346, in loads
return _default_decoder.decode(s)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\[User]\miniconda3\envs\fastapi\Lib\json\decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\[User]\miniconda3\envs\fastapi\Lib\json\decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

问题定位

首先想到的就是编码问题,然而像这样:response.encoding = 'utf-8'指定用utf-8解码后输出同样是乱码。

使用response.content.decode('utf-8')进行手动解码同样会报错:

1
2
3
4
5
Traceback (most recent call last):
File "xxx.py", line 37, in <module>
text = response.content.decode('utf-8')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x85 in position 0: invalid start byte

与此同时,其用postman等软件发送请求后的应答则完全正常。于是认为和UTF-8的解码步骤应该无关。

此时观察返回的字节内容(response.content):\x85i\x0f\x00d\xfe_\xb7\xfa\xaf\xdf\xd9\xfb\xf5J,发现这好像也不是UTF-8对应的字节格式,是经过处理的内容。
经过排查,发现原因在于网页端的应答使用了br压缩,而python的requests库默认不支持br的解码。

解决方法也很简单,有以下两种:

  1. 如果网页端支持gzip等其他方式,则可以在去掉POST请求头中accept-encoding内的br。
    1
    2
    # 修改POST的Header
    accept-encoding: gzip
  2. 或者也可以为requests增加解码br压缩的能力,只需要安装brotli库:
    1
    2
    # 在终端执行
    pip install brotli
    此时输出一切正常。

经测试,只要安装brotli库后,request就能正常解码,不需要手动在代码中引用brotli;
如果手动使用brotli.decompress(response.content).decode('utf-8')反而会报brotli.error: BrotliDecompress failed的错误

实验室算力资源实在有限,往往是多个人共用一台机器,环境与数据都在一台机器上。如果平常用的机器(A机)被占用,又有其他机器(B机)空闲时,想要利用其他机器来训练,要么将整个目录复制过去,要么在Pytorch中调用B机的显卡,或者就用本文的方案:将A机的文件挂载到B机上,让B机来执行A机上的程序。

挂载目录

可以用sshfs将A机的环境目录与程序数据目录挂载到B机上,在B机上运行程序即可。

1
2
3
4
5
# 在B机上执行
# 挂载环境目录
sshfs [A-User]@{A-IP}:/home/[A-User]/anaconda3/envs/[your_env] /home/[B-User]/anaconda3/envs/[your_env] # 如果B机上有同名的环境,另选一个挂载目录即可

sshfs [A-User]@{A-IP}:[A-dir] [B-dir]

跨机训练

此时可以通过终端连接B机进行训练,或者用VSCode连接B机操作;

1
2
3
4
5
# 在B机上执行
conda activate [your_env] # 如果挂载到了/home/[B-User]/anaconda3/envs下的目录
python train.py
# 或者
/home/[B-User]/anaconda3/envs/[your_env] train.py

在无法直接访问B机的情况下也可以通过A机ssh来操作B机训练。

1
2
# 在A机上执行
ssh [B-User]@{B-IP} "/home/[B-User]/anaconda3/envs/[your_env]/bin/python train.py"

测速

最好提前确保两机互联速度够快,可以使用iperf3软件测试直连速度,如果是百兆网络可能会严重影响训练速度。

1
2
3
4
5
6
7
8
9
# 两台机器都需要安装iperf3
sudo apt install iperf3

# 在A机上执行
iperf3 -s
sudo ufw allow 5201 # 如果开启了防火墙需要放行5201端口

# 在B机上执行
iperf3 -c [A-IP] -b 0 -n 1G -f M

如果B机输出的测试结果中比特率(Bitrate)在100 MBytes/sec以上即说明两机之间是千兆网络,适合用来进行跨机训练。

SSH密钥设置

为了避免两机之间每次使用ssh与sshfs时都需要输入密码,建议提前将两机的公钥(id_rsa.pub内容)拷入另一台机的授权文件(authorized_keys)中。

1
ssh-copy-id [User]@[IP]

参考: https://zhuanlan.zhihu.com/p/141714106

0%