<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Technicals on The Site of laekov</title>
    <link>/technical/</link>
    <description>Recent content in Technicals on The Site of laekov</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <copyright>&amp;copy; laekov</copyright>
    <lastBuildDate>Wed, 20 Aug 2025 00:00:00 +0000</lastBuildDate><atom:link href="/technical/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>HypeReca: 面向推荐模型训练的分布式嵌入向量数据库</title>
      <link>/technical/hypereca/</link>
      <pubDate>Wed, 20 Aug 2025 00:00:00 +0000</pubDate>
      
      <guid>/technical/hypereca/</guid>
      <description>闲话 - 前 这是一篇 ATC&#39;25 论文 的中文简要版本.
然而这篇文章在学术创新上实在乏善可陈，正好多说一点闲话了。这也是为什么没有在文章发表前就把博客写出来，不然万一被撤稿了可就搞笑了。
写这篇博客是 laekov 一直以来坚持要把自己发表的每篇文章都翻译成中文，因为曾经的 laekov 觉得凭什么论文都要用英文写呀，而且八股文读起来好麻烦呀，用中文简洁明了地把文章讲清楚不是更好吗。
然后天真的 laekov 读博五年一共也就中了两篇文章。这是第二篇，中稿时间是毕业前三个月。
HypeReca 这个名字是 Hybridly Partitioned Embeddings for Recommendation Model Training Acceleration 的各种胡乱拼凑里找了个听起来好听一点的。
背景 基于深度学习的推荐模型是现在主流的推荐算法，它分为学习元素特征的稀疏部分和学习元素间关系的稠密部分。 稀疏部分主要是非常稀疏的嵌入表 embedding tables，它们可能会有 TB 级别甚至更大，所以得要很好地分布式地存下来，并且支持高吞吐地读取和更新。 稠密部分通常由传统的 DNN 构成，属于计算密集型任务（比如 CNN / MLP），所以得用 GPU 来加速。
在做分布式训练的时候，这两部分由于特性不同所以采用了不同的并行方式：稀疏部分用模型并行（切分存储），稠密部分用数据并行（小模型，大 batch size）。 这两部分之间通过 all-to-all 集合通信来传输所需的数据和用于更新的梯度。 然后就会发现在 scale up 的时候两部分之间的通信是瓶颈，可能会占到迭代时间的 90% 以上。
解决方案 这篇文章的核心想法其实很直白：embedding data 有冷有热。 把频繁访问的热数据找出来，也用数据并行的方法来存，重复地放到所有 GPU 上。
接下来要解决两个问题：
首先，挑多少热数据比较合适？ 热数据越多，可以省掉的 all-to-all 通信就越多，但同步热数据所需的 all-reduce 量就越大。 这里正好是一个在单峰函数上找最优的 trade-off。结合实际数据建模观察一下即可。</description>
    </item>
    
    <item>
      <title>LLM Serving 文章阅读笔记</title>
      <link>/technical/llm-serving-papers/</link>
      <pubDate>Fri, 12 Jul 2024 00:00:00 +0000</pubDate>
      
      <guid>/technical/llm-serving-papers/</guid>
      <description>经典老文 orca Continuous batching: 把 prefill 和 decode 里的每个 token 打散重新做 batching.
vllm 用 page attention 来管理 kv cache 来应对碎片化, 以及利用 cpu memory 来 offload (这部分好像不是重点)。
OSDI&#39;24 一个会有一个 session 一篇文章讲同一个事，可怕。
Taming Throughput-Latency Tradeoff in LLM Inference with Sarathi-Serve 背景是现有 llm serving 系统（TRT-LLM, vLLM）要么等 decode 完了再 prefill, 要么有 prefill 就先做完整个 prefill, 导致 latency to first token 或者 decoding latency 不稳定。一个额外的坏处是这个事情影响 pp，因为 pp 里面有多个任务，每个任务时长不一样，就会有比较多的 bubble。
这文章把 prefill 任务 chunk 掉，这样调度的时候可以更好地复合 prefill 和 decode，控制 pp 里每个任务的 latency，从而对 decode 的 latency 也有保障了 (stall-free batching）。</description>
    </item>
    
    <item>
      <title>FastMoE 系统指南</title>
      <link>/technical/fastmoe/</link>
      <pubDate>Tue, 02 Jul 2024 00:00:00 +0000</pubDate>
      
      <guid>/technical/fastmoe/</guid>
      <description>FastMoE 是世界上首个开源的在 PyTorch 上支持 MoE 模型分布式训练的框架. 经过持续不断的更新与优化, 其在性能上相比各类竞品持续保持了一定的优势. 从 2021 年 3 月开源至今, 已经历了若干个发行版本, 亦有一些相关学术工作发表在各大会议和平台上. 此处对官方提供的公开资料进行汇总整理.
FastMoE 代码仓库 FastMoE 框架的开源版本开源在 GitHub 上. 链接 该开源版本支持 cuda 平台.
开源版本中也包含来自社区贡献的对 rocm 平台的支持, 但对新版本 FastMoE 的支持可能并不完善.
此外, 对于申威和一些其它国产加速平台, FastMoE 也有相应的私有版本. 如有兴趣, 请联系清程极智.
FastMoE 使用方式 FastMoE 作为 PyTorch 的插件存在, 推荐的使用方式是和 Megatron-LM 框架一起使用. 开源版本代码仓库中提供了修改不同版本 Megatron-LM 并与 FastMoE 一起使用的教程和参考补丁.
在FastMoE 官网(暂停维护)和代码仓库的中有更多文档可供参考.
FastMoE 及系列学术文章 FastMoE 支持专家并行的工作原理在一篇 arxiv 文章中进行了讲解.
arxiv原文 中文博客版本. FasterMoE 是一个发表在 PPoPP 学术会议上的工作. 其对于专家并行中负载均衡和通信计算重叠进行了研究. 该论文中所述的优化均已集成到 FastMoE v1.0.0 以后的版本中.</description>
    </item>
    
    <item>
      <title>在 PyTorch Distributed 中混合使用 mpi 和其它 backend</title>
      <link>/technical/pytorch-distributed-hybrid-mpi-backend/</link>
      <pubDate>Thu, 20 Jun 2024 00:00:00 +0000</pubDate>
      
      <guid>/technical/pytorch-distributed-hybrid-mpi-backend/</guid>
      <description>laekov 遇到的问题是希望使用 mpi 进行一些 cpu 的通信, 以及用 nccl 来进行一些 gpu 间的通信. // 没错, 说的就是让 FastDecode 支持模型并行.
众所周知, pytorch 和 mpi 的关系不太好的亚子. 然而 mpi 其实是最方便, 也是最适合大规模使用的. 虽然新版的 pytorch 试图引入 ucc backend 来支持 cpu 和 gpu 的混合通信, 但在较老的版本或一些特定环境里还无法顺畅地使用 ucc.
事实上 pytorch 支持创建不同 backend 的不同 ProcessGroup. 然而如果写如下一段代码, 就会发现并跑不起来.
dist.init_process_group(backend=&amp;#39;mpi&amp;#39;) ... g = dist.new_group(list(range(world_size)), backend=&amp;#39;nccl&amp;#39;) x = torch.ones(16, device=&amp;#39;cuda&amp;#39;) * (rank + 1) xs = [torch.empty_like(x) for _ in range(world_size)] dist.all_gather(xs, x, group=g) 甚至会获得一些在 ucx 里的错误栈, 再往上找会发现报错在 c10d::PrefixStore::set 这个函数里.</description>
    </item>
    
    <item>
      <title>FastDecode: 一种很大胆的分布式 LLM 推理系统架构</title>
      <link>/technical/fastdecode/</link>
      <pubDate>Thu, 21 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>/technical/fastdecode/</guid>
      <description>这是一篇 arxiv 文章 的中文简要版本.
摘要 这篇文章主要介绍了一种大语言模型的推理系统. 在自回归生成过程中, 序列中的元素 (token) 被挨个生成, 因此模型推理的序列长度 (sequence length) 为 1. 因此, 增大 batch size 对于 GPU 利用率的提升十分重要. 然而 KV-Cache 体积很大, 且与 batch size 成正比. 其大小阻止了 batch size 和 GPU 利用率的提升.
相比 vLLM 提出的 page attention 技术, FastDecode 对于 CPU 的利用进行了更加大胆的尝试. 其不仅利用了 CPU 的内存容量, 还利用了其计算能力和多机扩展能力, 从而达到了提升 batch size, 提升 GPU 利用率的目的, 并实现了端到端的推理吞吐量提升.
背景 在自回归生成过程中做 attention 时, 一个 token i 的特征向量 (feature vector) 会线性映射拆成 Qi, Ki, Vi 三个特征向量.</description>
    </item>
    
    <item>
      <title>实验室新机器安装步骤检查单</title>
      <link>/technical/pacman-machine-setup/</link>
      <pubDate>Wed, 13 Dec 2023 00:00:00 +0000</pubDate>
      
      <guid>/technical/pacman-machine-setup/</guid>
      <description>本检查单适用于在 PACMAN 实验室 安装新的服务器. 对于其它使用场景, 可视情况进行参考.
购买前 根据使用需求确定型号 PCIe 的连接方式是否符合预期 内存通道是否充足 在机房寻找一个合适的位置来放置机器, 需考虑如下因素 机柜的空位与承重能力 电源是否充足 网络 (如需使用 IB 网, 与需要的交换机是否足够近) 根据 CPU arch 确定是否接入某个 slurm 进行管理 现有的 slurm clusters: ja (AMD Epyc), nico (Intel Skylake) 注意: 除非这台机器永远只有一个人使用, 否则强烈建议接入 slurm 进行管理 起一个合适的 Hostname 向网络管理员申请一个合适的固定 ip 机器上架与硬件配置 (机房内) 检查机器完好 正确安装导轨 对机器的整体外观, 序列号进行拍照 插入系统盘和必要的存储, PCIE 设备 注意: 插入额外的 GPU 资产也需要事先对序列号和整体进行拍照 根据分配的固定 IP 配置 BMC 机器基础配置 (可远程) 在 NetBox 上更新相应信息, 包括但不限于序列号, 资产号, GPU 在 BIOS 中配置 CPU Sub-numa Clustering 以确保访存性能正确 Intel 简称 SNC, AMD 简称 NPS 可能在 ACPI 或 North Bridge 选项中 (视型号不同) PXE 引导安装 OS 机器软件配置 安装必要的基础软件 htop iotop iftop vim-common numactl rsync psutils ipmitool g++ 根据 Harry 的教程 配置 LDAP Client 安装 libnss-ldapd 和 libpam-ldapd 配置正确的服务器地址, base dn 和 LDAP 数据项 安装 nfs 客户端 安装 nfs-client nfs-common 挂载对应的 /home 配置 slurm 客户端 安装 libmunge-dev libmunge2 munge slurmd slurm-wlm libpam-slurm-adopt libpam-slurm libpmix-dev libpmi2-0 libpmi0-dev libpmi0 将主节点的 munge key 同步到新机器 /etc/munge/munge.</description>
    </item>
    
    <item>
      <title>CentOS 的防火墙和 ldap login</title>
      <link>/technical/88ab8d/</link>
      <pubDate>Thu, 21 Sep 2023 17:07:08 +0000</pubDate>
      
      <guid>/technical/88ab8d/</guid>
      <description>最近在实验室遇到一些情况必需搞一台 centos 的服务器, 但是还是想给它配置我们常用的一些东西, 于是踩了一些坑, 作一个记录.
sshd 在别的端口 我们用这个来提供外网的仅公钥的访问, 然而 cent 里面配了 sshd_config 里的 port 之后竟然没法从别的机器访问到这个 port. 关掉 selinux 也没用, 最后发现需要 disable firewalld. (什么企业级安全)
sssd ldap 无法 auth 相比 debian 底下使用 libnss-ldapd 和 libpam-ldapd, cent 下面用的是一个叫 sssd 的玩意. 然后使用 authconfig 来进行配置. 然而配好了之后可以 id 一个用户 , 却不能 getent. 发现需要在 sssd 配置文件里加上这个.
enumerate = true 然而还是无法用 ldap 用户密码登录, 一通查发现是因为
SSSD always uses an encrypted channel for authentication, which ensures that passwords are never sent over the network unencrypted.</description>
    </item>
    
    <item>
      <title>魔改 python-dbg</title>
      <link>/technical/5845d0/</link>
      <pubDate>Tue, 05 Sep 2023 19:10:33 +0000</pubDate>
      
      <guid>/technical/5845d0/</guid>
      <description>最近在一些奇怪的地方使用 pytorch. 那里的 python 十分的鬼畜, 以至于 python-debug 用不了. c 的栈打出来大概是这样的.
#110 0x00004ffff061c03c in _PyEval_EvalFrameDefault (f=&amp;lt;optimized out&amp;gt;, throwflag=&amp;lt;optimized out&amp;gt;) at ../Python-3.6.8/Python/ceval.c:3351 #111 0x00004ffff061865c in PyEval_EvalFrameEx (f=0x6, throwflag=8387296) at ../Python-3.6.8/Python/ceval.c:754 #112 0x00004ffff06192fc in _PyEval_EvalCodeWithName (_co=0x58000044c980, globals=&amp;lt;optimized out&amp;gt;, locals=&amp;lt;optimized out&amp;gt;, args=&amp;lt;optimized out&amp;gt;, argcount=0, kwnames=&amp;lt;optimized out&amp;gt;, kwargs=0x58000d8621b8, kwcount=2, kwstep=1, defs=0x580000449340, defcount=2, kwdefs=0x0, closure=0x0, name=0x5800003431c0, qualname=0x5800003431c0) at ../Python-3.6.8/Python/ceval.c:4166 #113 0x00004ffff0619768 in fast_function (kwnames=&amp;lt;optimized out&amp;gt;, nargs=0, stack=0x58000d8621b8, func=0x58000296f6b8) at ../Python-3.6.8/Python/ceval.c:4992 #114 call_function (pp_stack=0x500000804400, oparg=&amp;lt;optimized out&amp;gt;, kwnames=&amp;lt;optimized out&amp;gt;) at .</description>
    </item>
    
    <item>
      <title>python-dbg 使用中遇到的 auto-load-safe 问题</title>
      <link>/technical/b9d832/</link>
      <pubDate>Sat, 02 Sep 2023 19:39:25 +0000</pubDate>
      
      <guid>/technical/b9d832/</guid>
      <description>用 gdb 的 py-bt 来看一个 python 程序的调用栈是一个非常有用的工具.
然而今天在集群上尝试使用这个功能的时候发现了一些问题. 使用 debian 12 自带的 python3.11 时可以正常工作, 而使用 spack 安装的 python3.10 的时候就无法工作了. 最初怀疑 configure python 的时候没有带 --withdebug, 于是重新装了一个 python 还是不管用. 然后在仔细观察输出的时候发现 gdb autoload 竟然还有 safe path 一说, 故需要在 .gdbinit 中加入
add-auto-load-safe-path /home/spack/* 才能安全工作. (具体见这篇文档 )</description>
    </item>
    
    <item>
      <title>在 slurm 任务完成时通过 IM 软件向自己发送通知</title>
      <link>/technical/b8bb98/</link>
      <pubDate>Mon, 03 Apr 2023 18:07:52 +0000</pubDate>
      
      <guid>/technical/b8bb98/</guid>
      <description>代码地址
这事情好像原理挺简单的.
让 srun 在完成的时候给自己发个邮件, 用个脚本一直 tail 邮件, 并喂到 tg 的 bot 里, 根据 chat id 来发消息.</description>
    </item>
    
    <item>
      <title>使用 gdb 调试多机程序的方法</title>
      <link>/technical/70b9a2/</link>
      <pubDate>Thu, 22 Sep 2022 10:31:47 +0000</pubDate>
      
      <guid>/technical/70b9a2/</guid>
      <description>最近写了一些 mpi 程序, 但是有 bug, 且只有在多机上能够复现. 然而因为工程太大, 编译一次需要时间比较长, 所以反复 print 也并不方便解决问题. 而且集群上也没有图形界面, ssh -X xterm 的方法不太好使. 所以需要一些新的解决思路.
laekov 将目光瞄准了 tmux. 用 tmux new-session command 就可以在目标机器上新开一个进程, 跑 gdb. 然而 tmux 并不能继承环境, 所以需要再包一层脚本来重新加载环境 (这倒是和多机跑 mpi 程序差不多). 此外, 为了不需要手工一个一个进程地去 gdb 里开始, 可以用 gdb -ex &#39;r&#39; --args command args 来让它自动开跑. ex 还可以用来批处理设断点之类的, 非常方便.
另一个问题是 laekov 用的集群配置了 slurm, 是用 srun 来启程序的. 但是 tmux 命令会立即退出, 进程是跑在该用户的另一个进程里的, 而且这俩还没有父子关系, 无法用 wait 来等. 但是 srun 的进程退出之后 slurm 就认为这个进程跑完了, 甚至会清理 worker 上该用户的所有进程.</description>
    </item>
    
    <item>
      <title>如何使用 windows 笔记本的指纹解锁 linux</title>
      <link>/technical/e59478/</link>
      <pubDate>Mon, 18 Jul 2022 15:41:58 +0000</pubDate>
      
      <guid>/technical/e59478/</guid>
      <description>众所周知, laekov 在办公室有一台 nuc 装了 linux 主要用于工作, 另有一台笔记本用于其它工作. 作为一个锁屏强迫症, 每次 laekov 站起来去干啥的时候都会把两台电脑锁屏, 回来之后再分别解锁. 笔记本可以用指纹或者 iwndows hello, 而 nuc 就只能敲密码了. 不巧的是它还直接暴露在公网上, 于是密码设得比较长. 所以 laekov 希望用 windows 上的指纹来解 kde 的锁屏.
然后发现直接使用命令 loginctl (un)lock-session &amp;lt;id&amp;gt; 就可以实现(解)锁 kde. 配合 ssh 和 autohotkey 就可以实现一键开关锁.
但是这还是需要再额外按一次键. 然后发现 windows 有一个叫 task scheduler 的东西, 可以在锁屏和解锁的时候触发一些命令, 于是愉快地接入了 ssh 之后就可以方便地一次性解锁两台电脑辣!</description>
    </item>
    
    <item>
      <title>Recent Papers of Recommendation Systems</title>
      <link>/technical/a78ed7/</link>
      <pubDate>Fri, 08 Apr 2022 10:25:46 +0000</pubDate>
      
      <guid>/technical/a78ed7/</guid>
      <description>2023 EVStore: Storage and Caching Capabilities for Scaling Embedding Tables in Deep Recommendation Systems ASPLOS&#39;23 GRACE: A Scalable Graph-Based Approach To Accelerating Recommendation Model Inference ASPLOS&#39;23 AdaEmbed: Adaptive Embedding for Large-Scale Recommendation Models OSDI&#39;23 FlexShard: Flexible Sharding for Industry-Scale Sequence Recommendation Models arxiv 2022 RecD: Deduplication for End-to-End Deep Learning Recommendation Model Training Infrastructure arxiv Ekko: A Large-Scale Deep Learning Recommender System with Low-Latency Model Update OSDI&#39;22 PICASSO: Unleashing the Potential of GPU-centric Training for Wide-and-deep Recommender Systems arxiv HET: Scaling out Huge Embedding Model Training via Cache-enabled Distributed Framework VLDB&#39;22 HET-GMP: a graph-based system approach to scaling large embedding model training SIGMOD&#39;22 Fleche: an efficient GPU embedding cache for personalized recommendations EuroSys&#39;22 RecShard: statistical feature-based memory optimization for industry-scale neural recommendation ASPLOS&#39;22 BagPipe: Accelerating Deep Recommendation Model Training arxiv 2021 Accelerating recommendation system training by leveraging popular choices VLDB&#39;21 SPACE: Locality-Aware Processing in Heterogeneous Memory for Personalized Recommendations ISCA&#39;21 Software-Hardware Co-design for Fast and Scalable Training of Deep Learning Recommendation Models arxiv ISCA&#39;22 RecPipe: Co-designing Models and Hardware to Jointly Optimize Recommendation Quality and Performance MICRO&#39;21 2020 Kraken: Memory-Efficient Continual Learning for Large-Scale Real-Time Recommendations SC&#39;20 Distributed Hierarchical GPU Parameter Server for Massive Scale Deep Learning Ads Systems MLSys&#39;20 DeepRecSys: A System for Optimizing End-To-End At-Scale Neural Recommendation Inference ISCA&#39;20 </description>
    </item>
    
    <item>
      <title>Pandoc 的 short author 字段缺失 fix</title>
      <link>/technical/f86b57/</link>
      <pubDate>Tue, 15 Mar 2022 15:37:07 +0000</pubDate>
      
      <guid>/technical/f86b57/</guid>
      <description>laekov 搞了一个在 overleaf 里写 pandoc 的东西叫 panleaf, 并用它做一些愉快的 beamer slides.
但是 laekov 在做一个作者有七个人的 slides 的时候发现如果把七个人塞在正文的每页的底下, 就会巨长无比, overflow. latex 提供了 short author 功能, 在 beamer 里面正文的页脚只显示 short, 而 titlepage 显示全文. 但左右看了一圈发现 pandoc 的 author 字段并没有这样的支持. 而且即使不填 author 字段, 生成的 tex 文件里面还是会蹦出一个 \author{}, 且在自定义 latex template 的后面, 所以无法在 template 里面插 author 来解决.
laekov 于是找来了 pandoc 的 beamer writer (default.beamer, 也可能是 default.latex), 在里面找 author, 果然找到这么一段.
\author{$for(author)$ $author$ $sep$ \and $endfor$} 这么暴力怎么行, 于是加上一个 if 变成酱紫.</description>
    </item>
    
    <item>
      <title>Assetto Corsa G值球只有半个 bug 修复</title>
      <link>/technical/dadc0a/</link>
      <pubDate>Mon, 20 Dec 2021 22:14:48 +0000</pubDate>
      
      <guid>/technical/dadc0a/</guid>
      <description>laekov 最近在玩 assetto corsa 并试图学习循迹刹车, 因此需要一个加速度轨迹显示插件. 在 GitHub 上发现了一个上古仓库 竟然还能用, 但是卖家秀是
而 laekov 这里是
为啥参考线只剩小半个了？？？
由于 assetto corsa 的插件都是 python, 于是 laekov 愉快地看起了代码, 并发现了如下一段.
def drawCircumference(self, radius, center): ac.glBegin(1) nlines = max(4, int(100.*radius)) for i in range(nlines+1): x, y = self.gPlotter.plotG(center[&amp;#39;x&amp;#39;] + (sin(2*pi*i/nlines)*radius), center[&amp;#39;z&amp;#39;] + (cos(2*pi*i/nlines)*radius)) ac.glVertex2f(x, y) ac.glEnd() 大胆猜想是 python 或者 ac.gl 性能不足以支撑在一个渲染周期内画完整个圆. 于是想找一个 native 的 circle 的 api. 然而翻阅了一下上古的 python plugin document (竟然还是 google docs) 发现 ac 的 gl 只支持画点和多边形 (挠头).</description>
    </item>
    
    <item>
      <title>FasterMoE: 对大 MoE 模型训练的性能建模及优化</title>
      <link>/technical/181401/</link>
      <pubDate>Tue, 16 Nov 2021 11:16:21 +0000</pubDate>
      
      <guid>/technical/181401/</guid>
      <description>版权声明: 如需转载请先与 laekov 联系, 侵权必究. 序 Jiaao He 在 24 岁生日那一天收到邮件, 他在 ppopp 投稿的这篇文章被接收了. 这是他以一作身份投的第一篇 A 类会文章.
laekov 当时脑子一热, 开了一个坑, 决定把这篇文章的主要内容用中文写出来, somehow 地促进中文学术. (虽然多半并没有什么帮助)
在过去的小半年里他又经历了 artifact evaluation, camera ready, 制作 presentation slides 和录制视频 (很遗憾因为疫情没法去韩国开会了) 等等一系列事情, 对这个项目也有了更多的理解. 在 4 月的第一天终于把写文章时候的 prototype 变成了看起来还不错的代码, 并准备合并进 FastMoE. 正好写完这篇文章, 也当作是在 FastMoE 里使用 FasterMoE 的中文版文档了.
这篇文章的 pdf 正文在 ACM DL 上可以找到. (有 open access, 在任何地方都可以下载, 并用于非商业目的) 开会的时候用的 slides 和视频链接 在这里.
背景和简介 我假设看这篇文章的人已经知道什么是 MoE 模型了, 大规模的 MoE 模型现在有多重要 (也可能并不).</description>
    </item>
    
    <item>
      <title>slurmdbd 配置失败的坑</title>
      <link>/technical/5c630d/</link>
      <pubDate>Wed, 10 Nov 2021 00:09:16 +0000</pubDate>
      
      <guid>/technical/5c630d/</guid>
      <description>花了一晚上修的一个 bug. 记录一下. 先讲结论再讲故事.
slurmdbd 在更新 account 配置的时候, 有可能出现更新成功了, dump 出来是对的, 但跑程序失败 (requested resources not available) 的情况. 其中一个可能原因是 mysql 并没有成功写入, 于是认证失败. 解决方案是修改 slurmdbd 的配置文件, 使得其以 root 用户身份执行.
故事是实验室有同学要赶 PLDI, 需要独占某一些节点, 并防止懵懂的小朋友和他们抢占节点后不释放. laekov 给出的解决方案是在 slurm 中单独划分一个队列, 并仅对指定 account 开放. 这个操作 laekov 在另一个集群上已经熟练使用了. 但是 laekov 在用 sacctmgr 配置好 account 和 user 之后, 尝试 srun 任务, 发现提示 resources not available. 之前遇到过这种情况, 通过重启 slurmdbd 解决了问题. 但是这次重启任何 slurm 组件都没有解决问题.
laekov 查看了 /var/log/slurm-llnl/slurmctld, 发现提示 part_policy_valid_acct: job&#39;s account not known, so it can&#39;t use this partition.</description>
    </item>
    
    <item>
      <title>FastMoE: 一个高效 MoE 模型训练系统 - 初版之路</title>
      <link>/technical/6b400a/</link>
      <pubDate>Mon, 01 Mar 2021 18:03:51 +0000</pubDate>
      
      <guid>/technical/6b400a/</guid>
      <description>laekov 在 3月1号下午 3点1分 开源了 FastMoE 系统的代码。合作者是 KEG 实验室 的 xptree 和 sengxian。
简单讲，MoE 模型就是把神经网络里的一层复制若干份，称它们为专家（experts）。在计算时，引入一个额外的门（gate）网络来对于每个输入决定它被哪个专家所计算。
举个例子，一个 nlp 模型里的动词和名词可能会被不同的 expert 处理。这样可能会得到更精准的模型。模型部分 laekov 不太懂，不做更多讨论。
FastMoE 这个名字是 laekov 起的，包含了 laekov 关注的两层问题：
训练这样的模型怎么训得快（fast training）。 如何使得这个系统像吃快餐一样（fastfood-like）开箱即用。 训练性能 通常，expert 网络是一个 MLP，即多层全连接，即矩阵乘。一个值得注意的问题是，gate 会使得一个 batch 被打散。若简单地用 pytorch 来实现，则会导致 GeMM 运算降级为 GeMV 运算，这对 GPU 这样的现代并行计算设备来说是十分不友好的。测试发现朴素的实现在 V100 上仅能达到 500GFLOPs, 即峰值性能的 3% 左右。
注意到 expert 的数量不会太多，故 batch size / expert，即平均每个 expert 处理的 batch 中的元素依然是一个较大的值。因此考虑对 batch 中的 samples 按照 expert 进行重排，每个 expert 依然以 batch 形式处理输入。这样会更充分地利用硬件资源。</description>
    </item>
    
    <item>
      <title>HiDPI on XFCE4, Chromebook</title>
      <link>/technical/2f6dcb/</link>
      <pubDate>Wed, 03 Feb 2021 10:53:53 +0000</pubDate>
      
      <guid>/technical/2f6dcb/</guid>
      <description>由于众所不知的原因 laekov 在一处办公环境使用自己的 chromebook 进行办公.
之前的博客提到 laekov 的 chromebook 具有一块 3200x1800 的高分(瞎眼)屏. 而 laekov 在办公室开心地借来了一块和实验室那块看起来一样的 34 寸的带鱼屏, 然而插上之后才发现它的分辨率竟然是 2560x1080, 完全被 13 寸的笔记本屏幕给包含了. 本着屏幕 dpi 不重要, 面积才是王道的思路, laekov 十分容易地 disable 了笔记本的屏幕, 单独使用一整块 34 寸屏幕来进行工作.
laekov 在经历了 chromeos 的 ro rootfs 各种无语之后, 终于决心使用 crouton 的 xfce 环境作为自己的主力工作环境, 并配上了 i3lock 锁屏和熟悉的 urxvt.
然后问题来了: laekov 要抱着 chromebook 去开会! 当 laekov 拔掉 type-c dock, 看向 13 寸小屏幕的时候, 多年前在 laekov 的 (已经死掉的) mbp 上装 kde 之后出现的神奇一幕又出现了! 所有东西变得奇小无比, 需要配合放大镜才能分辨出屏幕上的字是 1 还是 l.</description>
    </item>
    
    <item>
      <title>在 ThinRouter 上开发网络（原理课）硬件测试仪软件部分的记录和一些经验</title>
      <link>/technical/3b42dc/</link>
      <pubDate>Tue, 22 Dec 2020 10:48:37 +0000</pubDate>
      
      <guid>/technical/3b42dc/</guid>
      <description>这个事情的 motivation 是被 harry 拉去上了一门叫 “高等计算机网络“ 的课, 而 harry 和 gyc 是本科生网络原理课的助教, 于是大作业的内容就是抱着 harry 的大腿给小朋友们做的硬件实验做一个测试平台. (harry: 你的老本行, 造 oj) 因为 laekov 的硬件水平四舍五入等于没有 (gg) 所以负责写前端.
VUE + ChartJS = gg laekov 多年没写过前端了, 没想到 angular 都已经 gg 了. 在 &amp;ldquo;尽量轻量化, 以后烧进 flash&amp;rdquo; 的指导思想 (还有 harry 的 push) 下选择了 vue.
功能里有一个重要的需求是画一张同学们的路由器带宽-帧大小的曲线. 要是有 matplotlib 就好了, 然而既然是在写 web 就只能搞 js 的轮子了.
然而 chartjs 需要给它一个生的 canvas DOM object. 但是 vue 的制造者似乎就是非常不喜欢开发者拿生的 DOM, 甚至把 document 对象都给屏蔽了. (?</description>
    </item>
    
    <item>
      <title>如何修改 htop 中一列的宽度</title>
      <link>/technical/b5a3f7/</link>
      <pubDate>Mon, 30 Nov 2020 17:19:45 +0000</pubDate>
      
      <guid>/technical/b5a3f7/</guid>
      <description>最近在某个公用集群上手工编译了 htop 给小伙伴们用. 然后发现大家的用户名都是学号, htop 并不能把用户名显示全, 于是追责麻烦. 然而 htop 似乎并不支持改列宽, 于是就自己去看代码改列宽了.
以下基于 htop 的 2.2.0 release 版本.
表项的宽度在 Process.c 里的 474 行. 这玩意是 hard coded 的 sprintf 的位宽.
表头在 linux/LinuxProcess.c 里的 205 行, 修改方法是在 title=&amp;quot;USER &amp;quot; 后面再加几个空格. (hard coding 真是让人崩溃啊)
然后可能会编译的时候说 struct Process has no member isKernelThread. 修的方法是在这个 c 文件的 146 行加括号. 注意不能改 .h 文件, 因为 .h 是在 make 的时候从 c 代码里抽取出来生成的 (什么鬼玩意)</description>
    </item>
    
    <item>
      <title>时隔六年, 我怎么又在修 fcitx 了</title>
      <link>/technical/0fbb2f/</link>
      <pubDate>Wed, 18 Nov 2020 22:54:10 +0000</pubDate>
      
      <guid>/technical/0fbb2f/</guid>
      <description>在宿舍买了一台新显示器, 2k.
发现 3337u 和 6400m 都不支持 2k 输出, 于是愉快地买了个 windows 游戏本当前端用.
因为有 rtx 2060 而且想打游戏, 所以只能用 windows 了, 最近又很不喜欢双系统 (因为要重启很麻烦)
于是找到了解决方案: 在 3337u 上开个 vnc server, 在 windows 里连过去.
虽然内网是千兆但是破笔记本迷之降速到了百兆, 于是网络也并不快. 要命的是 super 键会被 windows 吃掉从而无法使用 kde 里面炫酷的窗口搬移特技.
想起了陈年老相好 dwm. 于是又在这台 ideapad 上用上了 dwm, 并愉快地自己修改代码配置了 colorscheme 和各种神奇的热键.
然后用得好好的 fcitx 就跪了. ctrl + 空格打死也加载不出来输入法.
尝试了各种重启重装 fcitx-configure 和删配置文件, 都没用. 一脸茫然.
各种搜索尝试之后发现管用的是在 vnc 的 xstartup 里面加上
export GTK_IM_MODULE=&amp;#34;fcitx&amp;#34; export QT_IM_MODULE=&amp;#34;fcitx&amp;#34; export XMODIFIERS=&amp;#34;@im=fcitx&amp;#34; 然后就能解决问题了.</description>
    </item>
    
    <item>
      <title>使用 Shortcuts 让 linux desktop 与 iOS 间获得 airdrop 般的体验</title>
      <link>/technical/dc0e8e/</link>
      <pubDate>Thu, 09 Jul 2020 13:26:28 +0000</pubDate>
      
      <guid>/technical/dc0e8e/</guid>
      <description>laekov 在研究如何用手机远程开关家里的台灯的时候发现了 ios 里 shortcuts 这个神奇而好用(功能上) 的东西. 于是寻思着可以用 shortcut 解决手机/iPad 和 linux 桌面机之间文件和文字传输的问题, 于是进行了一些尝试.
为什么要上 AirDrop 因为它香啊. 可以在不同设备之间快速地传输文件.
比起开个微信传 / slack 传 / telegram 传这种还要让数据去地球另一端绕一圈的传数据方法, airdrop 它不用开聊天软件, 而且速度更快.
但是 AirDrop 的局限在于只能在 apple 设备之间使用. 对于桌面工作环境, laekov 还是更喜欢 linux (debian) + KDE, 用起来更爽一些. 所以每次在 desktop 和手机之间传输消息就成了一件非常麻烦的事.
如果是台式机, 不同的台式机, 台式机和笔记本, laekov 惯用 scp 进行文件传输. 但是 ios 下不存在一个好用没广告不收钱的 scp 软件. 但是 shotcuts 支持 run script over ssh, 就可以解决这个问题了.
Run script over ssh Shortcuts 提供的非常好的一项功能叫 run script over ssh.</description>
    </item>
    
    <item>
      <title>远程部署一个通过 B 站直播分发的实验室集群监控系统</title>
      <link>/technical/214397/</link>
      <pubDate>Fri, 19 Jun 2020 17:43:39 +0000</pubDate>
      
      <guid>/technical/214397/</guid>
      <description>突发奇想在 debian 上装了个 obs. linux 下 obs 可以直接 capture audio output 了, 于是可以在直播里放音乐了, 非常赞. 但是我的笔记本的这个 HD 6400 实在是支持不太了 obs 这种繁重的负载, 于是想到了利用实验室的台式机作为直播前端.
首先要解决的问题是如何连上台式机并使用 gui. 正好发现 teamviewer 可以用命令行启动.
$ sudo teamviewer daemon start $ sudo teamviewer info $ sudo teamviewer passwd &amp;lt;your passwd&amp;gt; 就这么就能获得远端的账号密码了, 就能用了, 非常开心. (虽然 daemon 获得号码可能要等一会儿, restart 若干次)
然后发现 obs 没法 window capture, 所有 window title 都是 unknown. 经过一翻搜索发现原因是 obs 的 locale 不对. 于是设了一下 LC_ALL 就能看到了.
然而 konsole 窗口是黑的一坨, 这和我手上的 debian 不太一样啊!</description>
    </item>
    
    <item>
      <title>一篇暗藏玄机的 Base64 简介</title>
      <link>/technical/5a37b3/</link>
      <pubDate>Thu, 13 Feb 2020 20:39:12 +0000</pubDate>
      
      <guid>/technical/5a37b3/</guid>
      <description>Base64 是一种常用的二进制到文本的编码方式, 应用非常广泛.
考虑这么一种场景, 两人之间现只能发送文字信息, 但他们要发送一张 jpeg 格式的图片.
如果尝试用文本编辑软件打开 jpeg, 将会发现是一大堆乱码. 原因是 jpeg 是二进制文件, 每个字节表示的东西几乎都不是给人看的字符, 自然没法解析出来.
而如果想把这些东西强行复制出来, 那更是一种灾难. 里面会有各种各样神奇的比如换行符, 甚至是\0 (文件结束符) 这种迷惑的东西. 自然是没法很好地以文本的方式传输的.
于是就有了这么一种把任意二进制文件都转化成没有奇怪特殊字符的方法.
首先把二进制文件或者任意字符串写成一串 01. 然后把相邻的 6 位合起来, 用 A-Za-z0-9+/ 一共 (64=2^6) 个字符来表示. 最后可能省下 2 个或者 4 个空位, 则用 0 补齐, 然后放一堆等号上去.
这样就可以把任意的文件, 比如文字, 图片, 视频都转换成肉眼可见, 易于复制和通过 http 之类的协议以及 json 之类的格式来传输的数据了.
下面是一些例子
hello world =&amp;gt; aGVsbG8gd29ybGQ=
我不知道 base64 是什么 =&amp;gt; 5oiR5LiN55+l6YGTIGJhc2U2NCDmmK/ku4DkuYg=
宝宝在这里给宝宝藏了一张小纸条: 6KaB5LiN6KaB5Y6755yL55yL5a6d5a6d55qE572R5piT5LqR6Z+z5LmQ5q2M5Y2V6YeM5aSa5LqG5LuA5LmI6L+35oOR55qE5Lic6KW/Pw== я говорю по русский плохо =&amp;gt; 0Y8g0LPQvtCy0L7RgNGOINC/0L4g0YDRg9GB0YHQutC40Lkg0L/Qu9C+0YXQvg==</description>
    </item>
    
    <item>
      <title>Ubuntu 发行版更新记录</title>
      <link>/technical/3132d1/</link>
      <pubDate>Tue, 21 Jan 2020 23:13:52 +0000</pubDate>
      
      <guid>/technical/3132d1/</guid>
      <description>就在刚刚运行着本网站的阿里云 ecs 经历了一次升级, 从 ubuntu 16.04 lts 升级到了 18.04 lts.
升级过程平稳, 但升级后发现这个 php 做的网站变成了源码. 目测是 php 跪了, 于是尝试修 php.
php5 仿佛已经不被支持, 于是换用 php7. 直接暴力 apt remove 再 install 就可以了, 配置会被保留.
然后发现 mysqli not found. 解决方法是在 /etc/php/7.2/apache2/php.ini 里面将 extension=mysqli 一行给 uncomment 掉.
然后就完事了.</description>
    </item>
    
    <item>
      <title>在若干不同机器上安装 Debian 并修了一些锅的记录</title>
      <link>/technical/29af09/</link>
      <pubDate>Mon, 13 Jan 2020 13:59:15 +0000</pubDate>
      
      <guid>/technical/29af09/</guid>
      <description>最近因为各种神奇的移动, 在不同的3台电脑上装了 debian, 并踩了不同的坑. 开一个文章来记录一下各种神奇的坑.
0 一台 2013 年的联想 ideapad 笔记本, 配备了 AMD HD 6400M 独显. 因为突然想起了 bios 的管理密码所以激活了独显. 于是想用独显来跑 opencl 之类的.
然而老的 amd crystal 驱动好像不是很支持? 时间有点久, 忘记了踩了什么坑. 总之 apt 瞎搞最后就装上了.
1 实验室师兄的 i7 + GTX 1070 + 4k 屏. 装 nvidia 驱动并 disable nouveau 是常规操作.
然后遇到的问题是 4k 屏对 gtk 的程序好像不是很友好. chrome 的地址栏和 ibus 之类的东西会变得非常小, 瞎眼. 解决方案是用 GTK_SCALE=2 这个环境变量. 但问题是这个环境变量不应该在开窗口的时候再设, 而是要放到 profile.d 里面. 然后就解决了问题.
然后 ibus 冥顽不化地占据了我的输入法. 然后发现 apt remove 之后就能愉快地使用 fcitx 了.</description>
    </item>
    
    <item>
      <title>Minimon: A minimal surveillance system based on buildroot for RaspberryPi</title>
      <link>/technical/1f8072/</link>
      <pubDate>Wed, 27 Nov 2019 21:18:35 +0000</pubDate>
      
      <guid>/technical/1f8072/</guid>
      <description>因为发现助教给炼丹任务提供了 64 张图片作为训练集, 64 张图片作为验证集, 所以果断放弃了炼丹任务. (update: 发现还是炼丹任务好做)
打算用 buildroot 从底向上 build 一个能跑起 python-gpio 的 linux. 另开一文记录一下坑们.
(补充) 计划 先不管镜像大小, 用 buildroot 搞出一个能跑的系统. (好像 buildroot 部分差不多了.) 实时性补丁 进一步裁剪内核. (即使不栽应该也比 raspbian 小很多了. 毕竟老师那边 raspbian 裁剪纪录是 200M, 而 buildroot 现在才不到 150.) build 使用了默认配置 $ make raspberrypi3_defconfig 节省了很多自己摸索的时间.
配置静态 ip 的时候发现可能是由于 networking 的版本问题, 必需要在 interfaces 配置文件里把 netmask 写在 address 上面, 否则不 work.
另外选装上了 openssh 以支持 ssh 登录. 在折腾了半天之后终于能 ssh 上树莓派上的系统了.
然后发现它有一个轻量级的 dropbear 作为 sshd.</description>
    </item>
    
    <item>
      <title>SCC@SC&#39;19 笔记</title>
      <link>/technical/b1c6c4/</link>
      <pubDate>Sat, 23 Nov 2019 06:05:51 +0000</pubDate>
      
      <guid>/technical/b1c6c4/</guid>
      <description>好的 scc@sc&#39;19 终于没有拿亚军
记个流水账
Benchmarking 好像没啥特别的.
一个新的发现是 HPL 的功耗飘可能是因为 GPU 功耗上升而不是计算 pattern? 回头仔细看看..?
内核的奇怪的锅 导致 idle 状态下 ssh 上一台机器就能跳 200w 的功耗 spike. 通过更新内核版本解决了该问题.
IB 卡烧掉了??? benchmark 本来早晨很早就交了而且数也还行. 然而中午玩着玩着发现 ib 卡没了. 尝试 pci hot reenable 失败之后重启并重新跑了 benchmark. 后来发现是 ib 卡在 gpu 风道里, 而我们给没插卡的节点的 gpu 风扇拔了一半的线, 另一半还是最低速运转的, 于是把 ib 给热傻了&amp;hellip;
SST 人脑挖矿 + 无脑跑 SST 第一个部分是给定 cpu 核心数, l1/l2 cache 的不同搭配之类的总共乘起来 5760 种选择, 让用 SST 搞出一种性能最好且不超过5000块钱的配置.
人脑挖矿 vs 暴力. 测算发现暴力应该能跑完所有点, 于是就暴力了一下.
听说别的队有试图人脑的&amp;hellip;</description>
    </item>
    
    <item>
      <title>Raspberry Pi 折腾记录</title>
      <link>/technical/0ab785/</link>
      <pubDate>Sun, 03 Nov 2019 21:49:27 +0000</pubDate>
      
      <guid>/technical/0ab785/</guid>
      <description>获得一个生日礼物 raspberry pi 已将近一年, 然而因为它只有四个核所以被嫌弃地闲置了很久. 近期因为上了嵌入式的课, 所以又开始了一轮折腾. 把一些有趣的事记录一下.
网络连接配置 老师说让我们先插上显示器配wifi, 之前我也是这么干的, 于是照做了.
然后想拿回家用, 家里没显示器, wifi 密码输入错误, 失联 ovo
后来想起直接给有线网口配个静态ip 就完事了. 和电脑直接对插就能访问 ovo.
延迟测试 发了一个示波器很好玩, 然而只有 windows 的 pc 端驱动差评.
GPIO 管脚控制居然是 python, 严重怀疑效率.
实验本身倒是很简单. 接下来是给 kernel 打实时性补丁. (中断响应优先级? 时间步大小? 感觉 很有趣)
视频流 网上看到一个例子是把 raspivid 的输出用 nc 接起来到 host 上用 mplayer / vlc 播放. 非常有趣就试了一下. cvlc 转发延迟略高. 直接 mplayer 放 h264 格式的视频非常流畅.
Modius NN 计算棒 去 intel 上找到了 openvino 作为 myriad 计算棒的驱动.</description>
    </item>
    
    <item>
      <title>Graph Processing Systems</title>
      <link>/technical/3fd4cd/</link>
      <pubDate>Wed, 25 Sep 2019 16:44:18 +0000</pubDate>
      
      <guid>/technical/3fd4cd/</guid>
      <description>GridGraph 师兄的文章. 主要 idea 是把邻接矩阵切成块 (p*p) 放到磁盘上顺序读来提升 io 性能. 单机.
GraphChi disk-based, parallel sliding windows, single consumer-level computer.
metis 不 work (???)
解决出入边都要考虑和写的问题.
按出边分块 shard. 入边按序存放, 在每个 shard 中为连续一段. 可加载进来.
解决了一些比较麻烦的问题比如数三角形.</description>
    </item>
    
    <item>
      <title>ISC&#39;19 马后炮</title>
      <link>/technical/6a12b3/</link>
      <pubDate>Mon, 01 Jul 2019 09:54:58 +0000</pubDate>
      
      <guid>/technical/6a12b3/</guid>
      <description>ISC&#39;19. 一场大概是退役失败的超算比赛.
我负责的 part 是 AI, 还有万年大锅 HPL, 以及神秘应用. 还有就是订保险订酒店联系赞助商blabla.
本来想帮忙搞 HPCC 的但是没有精力搞不动 ovo
AI AI 题是去年的 GB 论文 + 精调模型. 在解决了组委会提供的脚本里的一些性能上的 bug 之后顺利地训了起来. 而且按照原文里在上千个节点上并行训还能收敛来讲, 是可以在现有机器条件下随便数据并行的. (事实证明直接把整个训练集切成 10 个batch 也没有问题)
因为最终要求是精度, 所以请教了一些人, 得到的思路是 数据增强, ensemble. 数据增强不太写得动, 于是改脚本做了 ensemble 的 inference, 效果还不错. 比原文高了几个点. 但也没有特别闪亮的突破性进展. 唯一发现是 bn 用的是 training mode. (原因应该是 tf 的 bn 一直自带 bug, 如果用推理模式精度就是会炸掉) 于是推理的时候也应该 bs 越大越好. 于是就有了 dummy sample inference + unique 的一个脚本. 然后因为没有处理好 &amp;ldquo;//&amp;rdquo; 于是组委会还怀疑了半天为什么我的脚本有锅. 哭.
然后就是现场出了一个锅: unseen dataset 发下来一看居然是事前给出的 test set.</description>
    </item>
    
    <item>
      <title>Mac微信Bug修复手记</title>
      <link>/technical/f93221/</link>
      <pubDate>Fri, 10 May 2019 16:42:41 +0000</pubDate>
      
      <guid>/technical/f93221/</guid>
      <description>前段时间遇到 mac 微信出了一个锅.
部分微信群和联系人在电脑上收不到消息, 可以发消息, 但发出去一直显示转圈圈 (其实对方已经收到了), 切换窗口再切回来就连之前自己发的消息都不见了ovo
然而因为不太影响使用(可以在手机上看消息, 电脑盲回) 所以没太管. 但是作为一个强迫症还是不太能忍, 于是过了好久还是决定动手修一下.
mac下微信的本地数据文件在 /Users/laekov/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9. 初步估计是本地文件出锅了, 于是对它动手.
首先在mac端不上线的情况下手机拉了一个不影响别人的群, 然后用mac登录, 果然这个群属于bug群.
把 Message 目录移动为 Message_bak, 重新登录, 失去了所有聊天记录. 再次尝试使用上面那个群, 发现可以正常使用. 定位到问题文件在 Message 目录里.
发现 Message 目录下有 msg_[0-9]十种前缀的文件, 估计是对聊天记录进行了分桶. 大胆猜测是某个桶坏了.
于是等了一分钟后在群里发了一条消息, 发现只有 msg_6 开头文件被更新了. 大胆猜想是 msg_6 这个桶炸了.
另有有一个 MessageTemp 目录较大, 目测是数据文件. (比如消息, 图片, 视频) 猜想这里放的是元数据. 于是把旧的 MessageTemp 先拷回来.
然后恢复了 msg_1 开头的几个文件, 发现果然聊天记录回来了一部分.
挨个恢复除了 msg_6 以外的所有 msg_x 文件, 于是除了之前炸掉的记录以外, 聊天记录都回来了.
坏掉的文件就确实没法修了. 鬼知道.data格式是啥玩意. 完结撒花.</description>
    </item>
    
    <item>
      <title>DyNet 代码笔记</title>
      <link>/technical/bb68d3/</link>
      <pubDate>Sat, 01 Sep 2018 20:52:52 +0000</pubDate>
      
      <guid>/technical/bb68d3/</guid>
      <description>API角度 Python 功能没有 pytorch 完善. 参数收集等都需要手写.
CPP API 同 Python.
设计理念 类名为 Expression: 表达式 -&amp;gt; 明确定义 未执行.
Graph @xl nodes, parameter_nodes
inplace: forward_inplace_state { NOPE } 完全没支持inplace.
immediate_compute 立即执行.
提供backward方法, 但传入了loss的index.
Tensor 暴力绑定内存. (直接就是一个裸指针)
Expression (Variable) value() 方法真正执行expression并获取值. 调用ee(ExecutionEngine).
Autobatching 在执行cg的时候做. 具体代码在 exec.cc 里一个叫 incremental_forward_no_update的函数里.
使用 signiture 机制. 不同功能的function对应不同的signiture. 相同signiture的 合并.
Optimize 没有做. 只有一个找关键路径的简单算法.
Node(Functions) Spec推断 DimForward 专门维护 shape 信息.
forward 和 backward 放在一个子类里.
所有控制都由 Graph 接管. 包括所有 Variable 和 Nodes (Function)</description>
    </item>
    
    <item>
      <title>汇编 CSAPP Attack Lab</title>
      <link>/technical/6788d3/</link>
      <pubDate>Thu, 30 Aug 2018 08:59:09 +0000</pubDate>
      
      <guid>/technical/6788d3/</guid>
      <description>最近做 attack lab 感到虽然很头大但是很好玩.
主要分为两个 target: code injection 和 return hack
两个实验的原理都是栈向上溢出之后抹掉了一些 return address, 从而可以改写, 做任何你想做的事.
ctarget 比较简单粗暴, 可以直接跳到用户上传的字符串里面, 把用户数据直接当代码执行.
第一个子任务 可以直接跳转.
第二个子任务 需要把 cookie 找出来并写进 %rdi. 我最开始以为cookie是随机的, 于是去gdb里把 cookie 的内存地址给弄出来强行读了. 后来才发现可以直接 hardcode.
第三个子任务 同上, 没有发现这个 trick, 于是就从内存里读之后, 调用它提供的 sprintf 函数. 这个函数有很多的陷阱, 比如一定要把 %rax 设成 0, 不然会跳错. 然后打印的地址也得自己在栈里找. 更坑的是栈空间会被 sprintf 函数给抹掉, 所以必需得先把 %rsp 放低到很远的位置去, 不然就算打对了字符串, 注入的代码段也没有了, 还是会 segmentation fault.
好了现在问题又来了, 注入的栈只有 56 个字节. 如何把上面一长串代码塞进去. 其实有个简单的方法是继续向上溢出, 中间加一条 jmp. 但是懒惰的我强行使用各种办法把代码给压进去了. 比如 subl 比 subq 少一个字节, 于是可以只减 rsp 的低32位 esp.</description>
    </item>
    
    <item>
      <title>DyNet 论文笔记</title>
      <link>/technical/e51049/</link>
      <pubDate>Mon, 09 Jul 2018 11:38:28 +0000</pubDate>
      
      <guid>/technical/e51049/</guid>
      <description>DYNET 1701.03980
ABS cpp backend
lw graph representation
Problems easier debugging / maintaining large proj. express naturally Static vs Dynamic static pre-written model transfered to computation graph
graph can be well optimized
cannot deal with variable input size. NLP RNN
cannot deal with variable input structure. Tree NN, Graph NN
hard for complex flow-contronl logic (interface design)
nontrivial interface.
debug difficulty during execution
dynamic do computation on the fly
can be expensiveo flow control and variable sized inputs are in host language (python?</description>
    </item>
    
    <item>
      <title>CaPiano 基于 FPGA 和摄像头的现实增强钢琴</title>
      <link>/technical/7acc1f/</link>
      <pubDate>Tue, 12 Jun 2018 14:00:36 +0000</pubDate>
      
      <guid>/technical/7acc1f/</guid>
      <description>Queue 了一篇 CaPiano. 上午展示完. 人智课生产力低下. 把它 Dequeue 了罢.
这个项目的最初设想是造一个识别指尖的算法, 然后用它来弹钢琴并发出声音. 还有一个完全没有开动的二期工程是把它变成一个音游 / 录音机.
蓝图是美好的, 实现是丑陋的.
摄像头 过去一个半月的主要工作就是和这个 OV7670 (AL422B) 的摄像头做斗争. AL422B 是一个 DRAM 的 FIFO 队列, 通过巧妙地接 7670 和 422 的管脚可以实现把 422 作为 7670 的一个输出缓冲. 422 本来是用于简化这件事的. 在国外大学的 PA 文档里也是这么说的. 然而 422 这个东西最大的毛病就是没有 dataready 这个信号, 所以根本没法成功探索出什么时候可以读. 挣扎了很久之后我选择买了一个不带 422 的 7670.
7670 通过 SCCB 协议来进行配置, 有一些寄存器. 主要有用的是控制彩色的 12 和控制输出格式的 40. 本来想要 RGB565 加 QVGA 爽歪歪. 然而我的配置模块跑出来结果完全不对, 最后发现根本没设起. 降频到手工时钟都没有办法正常工作. 于是只好放弃, 使用默认的 YUV + VGA.</description>
    </item>
    
    <item>
      <title>人智的另一个作业. 教你 30 分钟写完 MNIST 作业</title>
      <link>/technical/75774b/</link>
      <pubDate>Fri, 18 May 2018 23:55:54 +0000</pubDate>
      
      <guid>/technical/75774b/</guid>
      <description>教你 30 分钟写完 MNIST 作业 laekov 2018.05.20
Overview 题目要求 随便用什么框架去 Kaggle 上做手写数字识别的数据集.
你可以选择自己写一个框架. (谁爱写谁写)
THU PACMAN 实验室最近在筹划写一个框架, 有兴趣的同学可以联系我.
最好多实现几个模型, 调调参, 写报告需要.
需要做的事 找一个框架 抄一遍 Tutorial 写一个处理数据 (csv格式) 的模块 写一个模型 写训练/验证/测试的东西 CNTK 框架 微软的框架. Python 文档见https://cntk.ai/pythondocs/index.html
安装. 见官网. pip, conda, install_cntk.exe 什么的都行.
略.
使用 CNTK 框架.
import os import cntk as C import numpy as np 轻松愉快.
处理 CSV 数据格式
第一行不用管
1234567890,0,0,...,255,0 一行一张图, 第一个是数字, 后面是28x28个0-255的灰度值.
可以用 pandas 之类的又麻烦又难用的库.
不如自己写个小函数.
def csv_reader(filename, batch_size = 1, is_test = False): with open(filename, &amp;#39;r&amp;#39;) as f: f.</description>
    </item>
    
    <item>
      <title>LIRS Plus</title>
      <link>/technical/3e470a/</link>
      <pubDate>Sun, 22 Apr 2018 17:59:13 +0000</pubDate>
      
      <guid>/technical/3e470a/</guid>
      <description>最近在做一个 Cache 替换算法的 PA. 系统结构课.
给的 Baseline 是 2010 年的一个 championship.
看了看现在用得比较多的通用算法叫 LIRS.
在 LIRS 基础上想方法优化.
瞎搞的东西把单核 miss 率降低得有点 surprising.
还没有更多的 benchmark 测试.
感觉有点意思.</description>
    </item>
    
    <item>
      <title>人智作业展示, 手把手教写拼音输入法</title>
      <link>/technical/fdd853/</link>
      <pubDate>Sat, 14 Apr 2018 20:59:25 +0000</pubDate>
      
      <guid>/technical/fdd853/</guid>
      <description>这篇讲义都是五笔打的
laekov 2018.04.12
Overview 作业要求 写一个拼音输入法, 一行一行地读拼音, 输出对应的汉语句子
84: 两小时就能写完
给出的数据 GBK编码的拼音-&amp;gt;汉字对应表 新浪新闻一年的文章 评分 基础2字模型 扩展3字模型 四字, 双词, 三词&amp;hellip; 需要写什么东西 拼音 2 汉字的 map 快速查找某个字/词词频的 map 估值函数和 infer 的算法 训练数据处理 最常用的16位编码是utf-8, 但是 Python 默认是 ASCII 的
所以在程序第一行写上
# -*- coding:utf-8 -*- Py 内部的 u&#39;一个字符串&#39; 可以用来表示 unicode 格式的字符串. 但是好像用不到.
创建 pinyin to 汉字的 map 读 GBK 文件的最简单的方法 with open(&amp;#39;somefile.txt&amp;#39;, &amp;#39;r&amp;#39;, encoding = &amp;#39;gbk&amp;#39;) as f: for (lineno, content) in enumerate(f): dealWithALine(content) content 的格式 wo 窝 我 握 渥 (五笔党词穷了) python 自带分割 py2ch_map = {} def dealWithALine(c): d = c.</description>
    </item>
    
    <item>
      <title>Lagrange插值, 三次样条插值和最小二乘拟合</title>
      <link>/technical/4aba20/</link>
      <pubDate>Wed, 28 Mar 2018 10:20:59 +0000</pubDate>
      
      <guid>/technical/4aba20/</guid>
      <description>看 paper 看烦了来贴点代码玩.
Lagrange插值就是一个多项式乘.
void genLagrangePoly(int n) { double *x = new double[n + 1]; double *y = new double[n + 1]; double *a = new double[n + 1]; double *tmp = new double[n + 1]; for (int i = 0; i &amp;lt;= n; ++ i) { x[i] = -5. + 10. / n * i; y[i] = f(x[i]); a[i] = 0; } for (int i = 0; i &amp;lt;= n; ++ i) { memset(tmp, 0, sizeof(double) * (n + 1)); tmp[0] = 1.</description>
    </item>
    
    <item>
      <title>Logs on setting up Jupyter</title>
      <link>/technical/7422c7/</link>
      <pubDate>Tue, 14 Nov 2017 13:06:54 +0000</pubDate>
      
      <guid>/technical/7422c7/</guid>
      <description>最近在尝试搭 python 的数据分析的环境. 总结一下遇到的一些坑.
用的是 14.04 这个有点老的 ubuntu.
nginx + jupyter jupyter 这个玩意的 web 写得不是很优美. 所以需要转发的地方蛮麻烦的.
本来想直接在 uri 里搞一下. 然后发现过于难受就放弃了, 重新配置了一个域名转发.
nginx 的 server 配置里需要加这么一段.
server { location ~* /(api/kernels/[^/]+/(channels|iopub|shell|stdin)|terminals/websocket)/? { proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # WebSocket support proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_pass http://127.0.0.1:8888; } } 其中有个Upgrade是这么定义的.
http { map $http_upgrade $connection_upgrade { default upgrade; &amp;#39;&amp;#39; close; } sendfile on; } google 了几个配置文件才弄出这么一个能用的.</description>
    </item>
    
    <item>
      <title>Web 爬虫二三事</title>
      <link>/technical/e522cb/</link>
      <pubDate>Fri, 15 Sep 2017 16:13:51 +0000</pubDate>
      
      <guid>/technical/e522cb/</guid>
      <description>最近 get 了一个技能叫爬虫. (可能早就 get 了只是没有实践过?)
然而我是用 js 写的. 毕竟自带异步而且瓶颈是延迟.
任务大概是说抓 wiki 的 list of people 上的人的 info.
然后发现可能它是一个不规则的索引结构.
每个二级索引都长得不太一样.
没事我们直接当作它就是二级索引结构.
然后发现有的企业也有 infobox. 这就很无语了?
没事我们判断一下它是不是有 occupation, born 这样的关键字吧.
然后大概就比较能看了? (才怪)
另外在看资料的时候才发现一种把 html plain 化的方式. 直接把所有的标签去了.
之前沉迷剥标签的我突然觉得自己真是蠢哭了.
嗯就是这么愉快.</description>
    </item>
    
    <item>
      <title>docker-compose DHCP and DNS</title>
      <link>/technical/f07783/</link>
      <pubDate>Tue, 08 Aug 2017 21:54:05 +0000</pubDate>
      
      <guid>/technical/f07783/</guid>
      <description>docker-compose 的网络
会自动加一些解析
把服务名和 ip 给绑起来
所以根本不用去搞 static ip
好像被这事坑了一万年了</description>
    </item>
    
    <item>
      <title>Rule-based Regular Routing Method</title>
      <link>/technical/4dc587/</link>
      <pubDate>Sun, 11 Jun 2017 20:35:19 +0000</pubDate>
      
      <guid>/technical/4dc587/</guid>
      <description>Upd: 代码来了 https://github.com/laekov/rbrrm
来 mark 一下我的 oop 组队大作业中窝肝的部分.
姚氏大作业果然有趣.
大概问题是这样的.
现在一个 pcb 上面有 (n*n) 的元件矩阵(忽略元件面积). 然后你要布线让每个元件都单独连着一条通往边界的电线, 我们管它叫这个点的 escape 路线. (最边上的就直接算作逃出去了)
然后电线只能横竖沿着格线走. 显然直接走是走不出去的. 所以你要找一个最小的 ( w ), 把原来的每行每列的中间都插上(w)条格线, 然后找一个总长最小 (或者如果你有其它的 feature 的话可以是尽量小) 的方案.
官方的的范围是 ( 80 ), 然后我算出来的 (80) 对应的 (w) 是 (23). 这个范围直接二分建图跑网络流已经非常吃力了. (或者直说要跑几天才跑得出来).
一个比较小的例子如图.
这个问题的标题叫作_rule based regular routing path_, 也就是说有某种直接用规则布线就可以了?
然后窝的第一个想法是神贪心, 然而在和大树讨论了很久之后也没有找到一种能让我们两个觉得靠谱且简洁优美的贪心.
然后窝就在想网络流是否有救. 在和 czr 讨论了一阵以及 czr 帮窝去 ieee 找了几篇 paper (btw, 校内网可以免费直接下 ieee 的论文不能更赞) 后发现了这么一个结论. 对于每个 ( w*w ) 的格子, 它的承载上限 (也就是说穿过这个格子的线的条数) 是 ( w ).</description>
    </item>
    
    <item>
      <title>PD大作业</title>
      <link>/technical/bd3e8b/</link>
      <pubDate>Sun, 23 Oct 2016 11:05:13 +0000</pubDate>
      
      <guid>/technical/bd3e8b/</guid>
      <description>据说本学期程设的大作业是写个魔方.
看到别人都开动了, laekov就有点方.
所以laekov也开动了. 为了表现laekov很弱就随手记录一下好了.
10.21 晚上9点左右开始写魔方类. 支持三轴整体转动和四种八向扭动. 其实是用两轴转动和一种扭动组合出来的. 然后发现写得不太对. debug到12点搞定.
10.22 早上有运动会. 九点左右开始写层洗ai. 中午随便吃了点然后接着写. 全程没make. 大概一点左右写完开始debug. 两点惊闻有项目. 直到晚上六点半去听心理讲座接着debug. 晚上回寝室接着debug. 很多公式和判定都有小小的问题. 不过幸好函数都分开写了, 调试还算方便. 晚上九点左右能跑过随机了. core部分基本完结撒花. 顺手完善了一下document. 准备开始看qt.
10.23 懒死了不想看qt. 晚上决定图形还是就用h5写吧.
Historical Comments lyzy at 2016-10-26T20:22:21 膜Qt大神 至今不会release
lyzy at 2016-10-26T20:27:43 我还是没有名字 I still have no name Todavia no tengo un nombre.
lyzy at 2016-10-26T20:28:57 怎么办 What to do ¿Cómo？
lyzy at 2016-10-26T20:29:21 太年轻 too young muy joven</description>
    </item>
    
    <item>
      <title>轮子们</title>
      <link>/technical/38ac37/</link>
      <pubDate>Mon, 19 Sep 2016 12:32:51 +0000</pubDate>
      
      <guid>/technical/38ac37/</guid>
      <description>一些可以用的轮子.
passportjs 用户登陆/管理模块
zmq 消息队列. 处理后台各种不能异步的请求.
openjudge-sandbox oj评测沙箱(还没搞懂)
react 前端框架
angularjs 更重量更强大的前端框架
bootstrap css板子
nodegit 顾名思义
grunt 开发自动化
threejs h5的3d绘图
phoria 另一个h5的3d绘图 // 似乎star比上一个多, 然而没有文档, 玩ball喽
// 开始考虑要不要重写srk了然而没有时间&amp;gt;_&amp;lt;</description>
    </item>
    
    <item>
      <title>MathJax简单配置</title>
      <link>/technical/7d45dd/</link>
      <pubDate>Sun, 20 Mar 2016 16:53:18 +0000</pubDate>
      
      <guid>/technical/7d45dd/</guid>
      <description>在网页上写数学公式怎么少得了MathJax. 然而这玩意因为功能复杂所以比showdown之类的库要难配置一些.
首先从Github上把它clone下来. 然后发现这玩意真的好大. 后来发现是有一堆迷之png.
别人家的cdn的速度从我这来看都不怎么样, 所以还是只能扔到自已的server上.
最简单的用法就是在html head里加一行
&amp;lt;script src=&#39;xxx/MathJax.js?config=default&#39;&amp;gt;&amp;lt;/script&amp;gt; 然后它就会用默认配置在网页加载的时候把那些玩意给转换了.
这里有一个config的文件可以选择. 在unpacked里的default.js里有很详细的说明. (虽然是英文的)
看上去能用了? 然后问题来了. 我的前端是先加载网页框架, 再用js去加载内容, 然而内容加载出来的时候MathJax已经把活干完歇菜了. 显然应该有什么控制单元能随时更新某个element. google了一下发现MathJax有个子类控制单元叫Hub. Hub有个方法叫Typeset, 能重新检查页面.
于是这么写?
$.post(&amp;quot;xxx&amp;quot;, {xx}, function(res) { $(&amp;quot;#xxx&amp;quot;).html(res.content); MathJax.Hub.Typeset(); }); 然而这样的话是不是我每加载一个listitem或者comment都要重新扫一遍整个页面啊? 卡死啦.
于是加了个triggerCount. 麻烦死了.
然后想想觉得没对, 肯定能直接改某个元素啊. 仔细看看document.
Typeset([element[, callback]])
对啊ovo可以直接指定element. 而且还各种类型都资瓷. 在类型这种问题上js比c高到不知道哪里去了.
于是代码写成
$.post(&amp;quot;xxx&amp;quot;, {xx}, functoin(res) { $(&amp;quot;#xxx&amp;quot;).html(res.content); MathJax.Hub.Typeset(getMyId()); }); 搞定啦.
然后config里还可以指定是用$$还是$之类的玩意.
然后似乎MathJax还自带Async一类的玩意?
感觉很赞.</description>
    </item>
    
    <item>
      <title>shiruku.点赞</title>
      <link>/technical/07f888/</link>
      <pubDate>Sun, 28 Feb 2016 10:41:28 +0000</pubDate>
      
      <guid>/technical/07f888/</guid>
      <description>造出了一个功能叫点赞qwq.
想起上周和czr讨论点赞到底应不应该重新从后端获取数据.ovo
然而这一部分的前端写得好丑啊. 然而后端水平进步了的感觉好开心. (虽然还是丑)
主要是前端动态渲染的方式会让js各种回调于是很讨厌. 而且$.post的异步在这种时候确实会造成麻烦.
jquery里面一个element被clone之后要先加到document里才能再修饰它的属性, 不然会有奇怪的事情OvO.
噢对laekov为了好玩允许一个人点0xf个赞. 为什么点赞只能点一个呢? 反正后端都写成这样了就多允许几个好了&amp;hellip;(其实可以调成0xff或者0x3f3f3f3f什么的23333)
另外也受到了知乎的一些启发. 评论什么的东西其实都可以加这么一个玩意, 反正都写出了通用的接口, 只是多几个接入而已. 感觉这种通用性的思路很有价值.</description>
    </item>
    
    <item>
      <title>shiruku.第三方登陆</title>
      <link>/technical/74c136/</link>
      <pubDate>Sun, 21 Feb 2016 17:32:39 +0000</pubDate>
      
      <guid>/technical/74c136/</guid>
      <description>听说造了登陆之后就没人愿意来评论了. 于是窝决定去造个第三方登陆.
于是花了一晚上造出了oauth组件. (其实有sdk的啊摔)
于是有了github登陆. 其实还有企鹅啥的. 然而企鹅就是强行降低网站的逼格这怎么行呢. (其实是企鹅强行要求sdk懒得搞了)
oauth的登陆简单过程是酱的(有点三次握手的感觉)
网站要去第三方申请一个application. 然后会得到client_id和client_secret. 然后把登陆的链接接到指定的页面去, 用get把client_id和泥要哪些数据传过去.
网站会和用户交流人生(登陆). 然后会用get方式调用callback, 这个是在注册application的时候指定的. callback的get参数里有一种东西叫code. 这东西要用.
用code来换access_token. 把code和client_id和client_secret一起当post参数传给第三方指定的第二个url. 如果没错会返回access_token, 这玩意是真正用来换数据的.
用access_token再去第三方提供的第三个url来get用户的数据, 比如avatar_url什么的.
那这和登陆有啥关系呢? 在第3步的时候如果泥得到了正确的access_token, 泥就可以认为用户正确登陆辣~
然后就发生了一件鬼蓄的事情: 窝在去和github换数据的时候, 莫名其妙地就被403了. 大概就是酱(get为粟)
function getData($url){ $opts = array(\&#39;http\&#39; =&amp;gt; array( \&#39;method\&#39; =&amp;gt; \&#39;GET\&#39; ) ); $context = stream_context_create($opts); $result = file_get_contents($url, false, $context); return $result; } 赶紧google了一下发现github会按照心情拒绝php发送的请求.
于是窝假装窝不是php而是善良可爱的少年就好了啊2333.于是强行骗人.
function getData($url){ $opts = array(\&#39;http\&#39; =&amp;gt; array( \&#39;method\&#39; =&amp;gt; \&#39;GET\&#39;, \&amp;quot;header\&amp;quot; =&amp;gt; \&amp;quot;User-Agent: Mozilla\&amp;quot; ) ); $context = stream_context_create($opts); $result = file_get_contents($url, false, $context); return $result; } 假装窝叫Mozilla.</description>
    </item>
    
    <item>
      <title>shiruku.缓存</title>
      <link>/technical/8059ec/</link>
      <pubDate>Sat, 20 Feb 2016 16:48:56 +0000</pubDate>
      
      <guid>/technical/8059ec/</guid>
      <description>之前版本找list都是去硬盘里枚举一遍文件. 本地我有ssd速度还行. 传到服务器上就慢暴了. 因为有导入之前的博文加起来也有几百篇. 枚举一遍就要开将近1k个文件. 这里O(1000)和oi里的概念完全不一样啊ovo几乎就是要几秒的意思了.
然后没有发现php怎么把东西常驻内存里. 于是灵机一动拿单个文件来存常用的数据. 然后就叫它伪缓存好了.
按照时间和需要对缓存进行更新, 每次查询所有东西的list只需要开一个文件. 果然就快多了好感动23333.</description>
    </item>
    
    <item>
      <title>Initial Commit</title>
      <link>/technical/19bc97/</link>
      <pubDate>Sat, 20 Feb 2016 09:50:36 +0000</pubDate>
      
      <guid>/technical/19bc97/</guid>
      <description>努力淦了几个月php, 终于在寒假结束前搞上线了. 开心.
之前写的东西实在太丑不能忍了所以造了个新的. 但是又舍不得万网的免费空间. 其实还有很多东西没写. 页面底部有github链接跪求star.
第三方登陆还没时间做. 私戳laekov得邀请码.
以及laekov真的很认真的做了UI. 虽然最后的结局是laekov在报复社会. 事实上laekov不具有造出好看的页面的能力ovo
于是可以愉快地log down一些其它的东西了好开心w. 虽然适配服务器有些周折ovo
于是挺晚了呢&amp;hellip;明天再接着写ovo
接着写
原来的博客主要是写题解啊. 构架的时候就没想过要搞其它飞机. 于是后来就啥都干不了了. 想加个版块都挺痛苦.
另外前端后端的代码夹杂在一起不开心.
要api化(向czr学习). 以及把事情扔给前端做. (于是现在加载速度感人)
强行把php当nodejs用是什么样一种体验? @我自己ovoovo
反正每月10G的流量总用不完&amp;hellip;所以就加图好了. 然而丑哭了qwq怪我喽. (找一个做美工的妹子当女朋友是laekov的人生追求23333)</description>
    </item>
    
  </channel>
</rss>
