最近终于快把课设搞完了,之前立下的给电脑清灰换硅脂的flag终于快到头了。由于之前没有专门准备工具,把CPU螺丝拧花了一次,结果去维修点花了大价钱才给修好,留下了心理阴影。这次决定现在网上买一套合适的工具,毕竟俗言 工欲善其事,必先利其器 嘛。

本文一共简要介绍三个点,品牌、材质和批头型号。

品牌

网上冲浪发现,大家推荐的品牌大多有三种,便宜一档的是南旗(Nanch),贵一档的是wiha和PB Swiss Tools。以本文写作时间(2022年3月)为例,南旗的22合1铬钒合金(Cr-V)套装50-60可以拿下来,S2合金版的大约100;PB Swiss Tools光是一把PB00的就要60多。

然而wiha这里出了个奇葩,跟小米合作做了米加螺丝刀套装,据网友说是硬生生拉低了自己的身价,达到了与南旗相同的百元价位。不过合作上似乎有点小插曲,最开始的套装盒子上是印了wiha商标的,后来新版本给整没了。但是官方宣传说除开更换了几个批头型号之外,性能没有任何变化,姑且相信吧。

材质

做螺丝刀批头的常见的材质有两种,分别是铬钒合金(Cr-V)和S2合金。因为不是专业相关人士,具体参数也无法做详尽的解释与分析,这里主要只看一个参数,硬度。

钢材硬度通常通过洛氏硬度(HRC)来判定,格式为HRCxx,其中xx为两位数,数字越大硬度越高。铬钒合金的批头硬度通常在HRC52左右,S2的在HRC58左右,即S2材质的批头硬度更大,本身更不容易变形。(大概这也是S2批头价格高的原因吧)

通常只说了Cr-V材质的螺丝刀直接按照HRC52看就行。更便宜的可能就是碳钢了,HRC只有40多,指不定稍微优秀点的螺丝都能把批头给你刮花喽(

批头型号

电子产品上的螺丝头常用的是十字形的(然而感觉上明明一字型的更好用力?)。十字形批头的编号为PH,数字越大直径越大,电路板上常用的以PH0/PH1居多。(命名规则:PH000/PH00/PH0/PH1/PH2/PH3,以此类推)

起因是之前闲着没事,自己动手编译了PyTorch和TensorFlow,然后把生成的轮子(.whl)留了下来,打算在之后需要使用的时候自己安装。这里顺便吐槽一句,PyTorch官方的wheel包里自带了cudaRT和CUDNN,搞得安装包动不动上1G(自己编译的非自带版本仅200M+),而且服务器还不稳定,下着下着就自动断线了= =

然后经典安装本地轮子命令:

pip install torch-1.9.0a0+gitdfbd030-cp36-cp36m-win_amd64+cu101.whl

然后直接提示说不支持我装这个包。Python版本是对的,编译和安装wheel时用的也都是64位版本,网上那些Python版本都搞不对的低级错误我怎么可能犯,当时一度怀疑是pip出了问题。试图到网上找pip的verbose选项,结果发现对于pip install指令并不支持这个功能,于是只好回到无头苍蝇状态,继续搜索有关轮子装不上的问题。

然后恰好看到这个提问,里面说pip会使用文件名来判断当前wheel是否支持目标平台。(使用pip debug --verbose可以查看当前平台pip支持的所有目标平台标识符)

然后仔细一想,为了区分CPU和不同CUDA版本下编译出来的轮子,我在每个文件末尾添加了CUDA版本信息,如上面命令中的+cu101,于是猜测是不是这个动作干扰了pip对轮子信息的判定。结果删了之后马上就好了= =

于是得出结论,不要轻易修改python wheel的文件名;如果一定要添加辅助信息的话,可以在版本号后面用加号+链接添加所需要的信息,例如PytTorch自己编译时自动添加的git版本号。

Jupyter Notebook是Jupyter Lab的上一代产品,虽然奠定了Jupyter系列的基本用法与功能,不过可扩展性还是差了点,不像Jupyter Lab一样,直接提供了基于json的用户可定义配置文件。

Jupyter Notebook的默认代码字体竟然是宋体,看得我人惊呆了。jupyterthemes包能够修改Jupyter Notebook的字体,但是和主题绑定在一起了,显得不太清真。于是打算手动修改内置CSS样式。找到notebook的pip包的static/style/style.min.css,修改其中.CodeMirror样式,添加类似于font-family: Consolas;的字体声明,重启Jupyter Notebook服务生效。

问题1:

pytorch\aten\src\ATen\native\quantized\cpu\qembeddingbag_unpack.cpp(131): error C2039: "Fused8BitRowwiseQuantizedSBFloatToFloat": 不是 "fbgemm" 的成员

类似的,“XXX不是XXX的成员”的问题很有可能由相同的原因引起。

我这里的问题是git checkout的时候忘记更新依赖版本了。理论上的正确操作是git checkout之后再git submodule update --init --recursive操作。如果不小心编译了一半,修改了submodule里的文件的话,可以先git submodule deinit --all -f清除所有文件后再重新初始化submodule。这个重新初始化的过程不消耗流量,数据已经在第一次更新submodule的时候保存到本地了。

问题2:在编译torch/csrc/stub.c时,遇到

VC\Tools\MSVC\14.29.30133\include\cstdlib(19): error C2061: syntax error: identifier 'noexcept'

这个是由于编译器把C++头文件cstdlib当成C源代码来编译了,导致C++专有语法noexcept认不出来报错。我这里产生问题的原因是Python的pyconfig.h中不分青红皂白地写了#include <cmath>这句话,相当于默认当成C++头文件使用了,因而在编译stub.c的时候引入了C++语法导致报错。

我的解决方法:把

#include <cmath>

改成

#ifdef __cplusplus
#include <cmath>
#else
#include <math.h>
#endif

然后就是test模块里的一堆bug= =
比如说什么模块导错了、数据类型不对一类的,见啥改啥就行了

浏览NVM全貌

sudo ipmctl show -memoryresources

以内存插槽为单位展示AEP信息

sudo ipmctl show -dimm

NVM Region(区域)信息

Linux以Region区域为单位来划分NVM区域的硬件特征,或者说是用途。一个区域内的NVM具有相同的特性,比如都做内存(Volatile)或者非易失存储(Appdirect,可供系统/用户作为数据设备读写)。可以理解为把NVM DIMM再抽象、划分为内存或硬盘(因为NVM的确同时具有两种设备的特性)。

sudo ipmctl show -region

把一个CPU下的所有PMEM划成一个区域

官方文档中提到,Region不能跨CPU插槽,估计是因为NUMA影响性能的原因。

sudo ipmctl create -goal -socket 0x0000 PersistentMemoryType=AppDirect

制造单个无交错的PMEM区域(可用于测试单条PMEM性能?)

sudo ipmctl create -socket 0x0000 -dimm 0x0001 -goal PersistentMemoryType=AppDirectNotInterleaved

这条命令会报错,但配置完重启后还是会达成预期效果= =

查看已有区域使用情况

sudo ndctl list -Ruv

查看已有Namespace

Namespace命名空间,可认为是设备上的分区,可用作磁盘或分区,格式化后供系统或用户使用。

sudo ndctl list -Nuv

创建新Namespace

sudo ndctl create-namespace -t pmem -m fsdax -s $((128*1024*1024*1024)) -n default -r region0

注意如果使用的Region是DirectApp Interleaved的话,这里的size必须要是区域设备数的整数倍,不然数据不能均匀分布,会报错。

删除Namespace

sudo ndctl disable-namespace -r region0 namespace1.0
sudo ndctl destroy-namespace -r region0 namespace1.0

重置PMEM(比如异常断电后namespace找不回来)

sudo ndctl destroy-namespace all -f  # 删除namespace
sudo ipmctl delete -f -dimm -pcd     # region配置都给你扬喽

其他参见ipmctl/ndctl官方文档,或者巨硬的快速上手教程