Esper 发布的文章

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官方文档,或者巨硬的快速上手教程

根据RFC,IPv6有两种地址管理方式,分别是有状态Stateful无状态Stateless。如其名所示,Stateful模式下主机IPv6地址由路由器分配,而Stateless模式下主机IPv6地址根据协议自身计算得出。大概可以猜到的是,Stateful模式下管理较为方便(如DDNS等),而Stateless模式则是减轻了路由器的工作负担(毕竟IPv6地址池那么大一个,记录所有地址还是很消耗资源的)。

OpenWrt默认使用了Stateless的方式管理IPv6下的内网NAT,然而我想知道内网设备中有多少获取到了IPv6地址= = 于是试图网上冲浪找出配置方法。

左摸索右摸索,也不知道是不是关键词用得不对,老半天才在一篇国人折腾IPv6的文章中摸到了个边。注意到文中配置有个未经解释的ra_management参数,搜了一下发现OpenWrt官网上给出了极为惨淡的解释:

ra_management    integer    1        RA management mode
                                     0: no M-Flag but A-Flag
                                     1: both M and A 
                                     2: M but not A

这里提到了AM两个标志位,而这两个标志位正是DHCPv6中用于控制StatefulStateless模式的标志。

Flag Type Name Message Manual SLAAC DHCPv6
A Autonomous Prefix Information No Yes Maybe
M Managed ICMPv6 134 RA No No Yes
O Other ICMPv6 134 RA No Maybe Yes
L On-Link Prefix Information No Yes Yes

也就是说,理论上,将ra_management设置为2的话就可以强制启用Stateful模式管理IPv6地址。有待试验。

参考: https://blogs.infoblox.com/ipv6-coe/the-ipv6-prefix-information-option-or-fun-with-the-l-flag/

大意了,没有闪

起因是在VS新建了一个C++项目,然后试图引用一个用C写的函数库。结果编译运行的时候报错了,提示无法解析的外部符号。根据常识,这个问题一般与C++的函数重载有关,但是在仔细检查了库函数和调用时函数的签名之后发现并没有问题。用grepdumpbin对着编译出来的.lib静态库文件捣腾了老半天,也愣是没有找出问题所在。

左思右想,唯一的端倪在于用dumpbin观察.lib静态库文件时发现,编译出来的库函数是没有带C++后缀的,而报错的地方所调用的库函数是带了C++后缀的,这也正是导致出现函数名不匹配的地方。无奈之下只能去网上冲浪,带着我也描述不清的问题试图找出解决方法。

在万能的StackOverflow上看到了这个回答之后才意识到,函数名是在编译期确定的。由于头文件本身作为源文件参与编译,编译器只能通过源文件信息来确定这是C还是C++代码。很显然,.c后缀的被MSVC作为C代码编译,而.cpp文件则是作为C++代码编译。

而正是这细微的编译规则差异导致了本次的问题:在库函数源代码中,由于是以.c源文件的形式参与编译,遵循了C语言不允许函数重载的规则,编译出来的函数名就是头文件中所定义的函数名;而在我写的调用程序中,因为使用了.cpp格式的文件,代码使用了C++规则编译,因而给头文件中定义的函数名加上了C++的小尾巴(如@UAEXXZ这种)。在之后的链接过程中再用C++风格的函数名去匹配C风格的函数体,由于两者名字不一致,就产生了无法解析的外部符号问题。

解决方法也非常简单,在写C/C++混合调用的程序时,被调用者(主要是头文件)最好加上用#ifdef __cplusplus包装的extern "C"标记,以确保最大的兼容性