<?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>Tech Notes on Ping Zhou’s Personal Blog</title>
    <link>/notes/</link>
    <description>Recent content in Tech Notes on Ping Zhou’s Personal Blog</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Sat, 18 Apr 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="/notes/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>基于 Emacs org-mode 和 hugo 的 Blog 工作流</title>
      <link>/notes/20260418_emacs_org_hugo_workflow/</link>
      <pubDate>Sat, 18 Apr 2026 00:00:00 +0000</pubDate>
      <guid>/notes/20260418_emacs_org_hugo_workflow/</guid>
      <description>&lt;div id=&#34;outline-container-org2ee75ba&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org2ee75ba&#34;&gt;Introduction&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org2ee75ba&#34;&gt;
&lt;p&gt;
我经常使用 Emacs Org-mode 来写blog。虽然有很多其他笔记工具和方案，但我一直觉得没法取代 Org-mode，比如Org-mode里的 Babel 代码块，内嵌LaTex公式，GUI下图表预览，表格自动求值等功能，实在是很方便。Emacs Org-mode 也天然支持将众多 org 文件笔记通过链接组织成个人知识库。
&lt;/p&gt;

&lt;p&gt;
不过，现有的工作流基于标准的 &lt;code&gt;ox-publish&lt;/code&gt; 导出 HTML，样式略显陈旧，如果支持更美观的主题，需要很多手动配置。
&lt;/p&gt;

&lt;p&gt;
最近对orgmode工作进行了一次升级：引入 Hugo 渲染引擎（搭配 PaperMod 主题），同时保留了纯粹的 Org-mode 创作体验。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org2f869ab&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org2f869ab&#34;&gt;工作流的演进&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org2f869ab&#34;&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-org23cf43b&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org23cf43b&#34;&gt;过去：Org -&amp;gt; HTML (ox-publish)&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org23cf43b&#34;&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;优点：流程简单，完全受 Emacs 控制。&lt;/li&gt;
&lt;li&gt;缺点：网页样式极其基本，移动端适配差，缺乏搜索和标签功能。&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org7ef909b&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org7ef909b&#34;&gt;现在：Org -&amp;gt; HTML Fragment -&amp;gt; Hugo (PaperMod)&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org7ef909b&#34;&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;改进：采用 Hugo 作为渲染引擎，利用 PaperMod 提供现代化的 UI。&lt;/li&gt;
&lt;li&gt;核心逻辑：利用 Emacs 的 &lt;code&gt;ox-html&lt;/code&gt; 将 Org 导出为纯净的 HTML 片段，再交给 Hugo 进行最终装配。&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org671ad1d&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org671ad1d&#34;&gt;关键技术点&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org671ad1d&#34;&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-orgc29a37d&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;orgc29a37d&#34;&gt;1. 自动化导出脚本：publish-hugo.el&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-orgc29a37d&#34;&gt;
&lt;p&gt;
这是整个流程的“心脏”。它是一个 Emacs Lisp 脚本，通过 Org 内置的 &lt;code&gt;ox-html&lt;/code&gt; 导出器实现精准渲染，同时负责元数据注入和路径修正。
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-elisp&#34;&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;pz/export-all-to-hugo&lt;/span&gt; ()
  (&lt;span style=&#34;font-weight: bold;&#34;&gt;dolist&lt;/span&gt; (section &#39;(&lt;span style=&#34;font-style: italic;&#34;&gt;&#34;notes&#34;&lt;/span&gt; &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;quantum&#34;&lt;/span&gt; &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;me&#34;&lt;/span&gt;))
    (&lt;span style=&#34;font-weight: bold;&#34;&gt;dolist&lt;/span&gt; (file (directory-files (expand-file-name section) t &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;\\.org$&#34;&lt;/span&gt;))
      (&lt;span style=&#34;font-weight: bold;&#34;&gt;with-current-buffer&lt;/span&gt; (find-file-noselect file)
        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#23548;&amp;#20986;&amp;#20026; HTML &amp;#29255;&amp;#27573;
&lt;/span&gt;        (&lt;span style=&#34;font-weight: bold;&#34;&gt;let&lt;/span&gt; ((html-content (org-export-as &#39;html nil nil t)))
          &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#20462;&amp;#22797;&amp;#36164;&amp;#28304;&amp;#36335;&amp;#24452;
&lt;/span&gt;          (&lt;span style=&#34;font-weight: bold;&#34;&gt;setq&lt;/span&gt; html-content (replace-regexp-in-string &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;\\.\\./images/&#34;&lt;/span&gt; &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;/images/&#34;&lt;/span&gt; html-content))
          &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#20889;&amp;#20837; Hugo content &amp;#30446;&amp;#24405;
&lt;/span&gt;          (&lt;span style=&#34;font-weight: bold;&#34;&gt;with-temp-file&lt;/span&gt; dest-file
            (insert &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;---\n&#34;&lt;/span&gt; (format &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;title: \&#34;%s\&#34;\n&#34;&lt;/span&gt; title) &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;math: true\n---\n\n&#34;&lt;/span&gt;)
            (insert html-content)))))))
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org37929d0&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org37929d0&#34;&gt;2. 构建与部署：build.sh &amp;amp; deploy.sh&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org37929d0&#34;&gt;
&lt;p&gt;
实现“一键发布”的两个 Bash 脚本：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>LlamaPi 初步试用 RWKV, Ollama</title>
      <link>/notes/20250621_llamapi_rwkv/</link>
      <pubDate>Sat, 21 Jun 2025 00:00:00 +0000</pubDate>
      <guid>/notes/20250621_llamapi_rwkv/</guid>
      <description>&lt;p&gt;
最近RWKV有不少进展，RWKV-7出了思考模型 &lt;code&gt;rwkv-7-world-g1&lt;/code&gt; ，RWKV-8也即将发布。
&lt;/p&gt;

&lt;p&gt;
RWKV的模型架构，在计算量和内存上相比Transformer有很大的优势，对于LlamaPi这种在边缘设备上运行的应用很有吸引力。因此尝试在LlamaPi上适配RWKV，看看效果如何。
&lt;/p&gt;

&lt;p&gt;
目前初步尝试，总的来说不太成功，可能是使用方法或适配上还有些问题，模型始终不能很好的遵循系统指令，生成符合要求的响应。
&lt;/p&gt;

&lt;div id=&#34;outline-container-orga0c8feb&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orga0c8feb&#34;&gt;llama.cpp运行&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orga0c8feb&#34;&gt;
&lt;p&gt;
按照&lt;a href=&#34;https://rwkv.cn/tutorials/intermediate/llamacpp&#34;&gt;文档&lt;/a&gt;步骤：
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;编译最新的llama.cpp&lt;/li&gt;
&lt;li&gt;下载 &lt;code&gt;rwkv7-g1-1.5b-20250429-ctx4096&lt;/code&gt; ，转换成gguf，Q8&lt;sub&gt;0量化&lt;/sub&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
用 &lt;code&gt;llama-cli&lt;/code&gt; 命令行运行，提示词参考LlamaPi：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-shell&#34;&gt;./build/bin/llama-cli -m models/rwkv7-g1-1.5b-20250429-ctx4096-Q8_0.gguf -p &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;Your name is Skyler. You are a helpful assistant.\n\n&#34;&lt;/span&gt; -cnv -t 4 -ngl 99 -n 500
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
启动后本来应该就进入对话的，但它先进入了自嗨模式，输出了一大通不相关的东西，然后才停下进入提示符。这可能还是因为我设了n=500的参数，否则不知道它什么时候会停下：
&lt;/p&gt;


&lt;div id=&#34;orgca43088&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2025/2025-06-21_14-37-03_screenshot.png&#34; alt=&#34;2025-06-21_14-37-03_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
然后检查一下提示词的有效性，结果是完全没用：
&lt;/p&gt;

&lt;pre class=&#34;example&#34; id=&#34;org9a55b9b&#34;&gt;
&amp;gt; hello, what&#39;s your name?
 My name is [My name]

&amp;gt; who are you?
 My name is [My name]

&amp;gt; 
&lt;/pre&gt;


&lt;p&gt;
命令行不行，那试试Web界面？
&lt;/p&gt;
&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-shell&#34;&gt;/build/bin/llama-server -m models/rwkv7-g1-1.5b-20250429-ctx4096-Q8_0.gguf 
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
先设置一下系统提示：
&lt;/p&gt;


&lt;div id=&#34;orgc1d1b6c&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2025/2025-06-21_14-43-42_screenshot.png&#34; alt=&#34;2025-06-21_14-43-42_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
试一下，这次系统提示词似乎有效了。
&lt;/p&gt;


&lt;div id=&#34;orgf1c0f69&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2025/2025-06-21_14-45-16_screenshot.png&#34; alt=&#34;2025-06-21_14-45-16_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
试试LlamaPi的完整提示词：
&lt;/p&gt;


&lt;div id=&#34;orgaddeb5f&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2025/2025-06-21_14-47-58_screenshot.png&#34; alt=&#34;2025-06-21_14-47-58_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;</description>
    </item>
    <item>
      <title>LlamaPi: Experiments with VideoCore GPU</title>
      <link>/notes/20241116_llamapi_update_rpi_videocore/</link>
      <pubDate>Sat, 16 Nov 2024 00:00:00 +0000</pubDate>
      <guid>/notes/20241116_llamapi_update_rpi_videocore/</guid>
      <description>&lt;p&gt;
As mentioned in my previous posts, I&#39;ve been trying to get LlamaPi to run with VideoCore GPU on Raspberry Pi, hoping to further boost generation speed.
&lt;/p&gt;

&lt;p&gt;
Well, that effort might have just come to a conclusion&amp;#x2026; TL;DR is that VideoCore on Raspberry Pi is not well suited for such computation - in fact, it is even much slower than the ARM CPUs on Raspberry Pi.
&lt;/p&gt;

&lt;p&gt;
In case I need them again, here are some of the records of my experiments.
&lt;/p&gt;</description>
    </item>
    <item>
      <title>LlamaPi Update - Gemini Support</title>
      <link>/notes/20241027_llamapi_gemini/</link>
      <pubDate>Sun, 27 Oct 2024 00:00:00 +0000</pubDate>
      <guid>/notes/20241027_llamapi_gemini/</guid>
      <description>&lt;p&gt;
LlamaPi now supports Gemini as its backing LLM, in addition to local LLM and Coze.
&lt;/p&gt;


&lt;div id=&#34;org9cdce84&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2024/2024-10-27_22-35-35_screenshot.png&#34; alt=&#34;2024-10-27_22-35-35_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
On Gemini side:
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;Test the prompt (system instruction) for using with LlamaPi.&lt;/li&gt;
&lt;li&gt;Create an API key (may need to create a project first).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
On LlamaPi side:
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;Create a wrapper using Gemini Python SDK.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
In order to support multiple backing LLMs, major refactor was done to the LlamaPi code.
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;Create a common base class &lt;code&gt;LlamaPiBase&lt;/code&gt; for all three scenarios (local, Coze, Gemini). The base class includes the common functionalities like the UI, audio, ASR, etc.&lt;/li&gt;
&lt;li&gt;Created subclasses for local LLM, Coze and Gemini respectively. They extend the base class and implement the logic for interacting with backing LLMs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
With this refactor, it will be easier for me to add support for other LLMs in the furture.
&lt;/p&gt;</description>
    </item>
    <item>
      <title>LlamaPi Update - Llama-3.2 3B</title>
      <link>/notes/20241001_llamapi_updated/</link>
      <pubDate>Tue, 01 Oct 2024 00:00:00 +0000</pubDate>
      <guid>/notes/20241001_llamapi_updated/</guid>
      <description>&lt;p&gt;
I just updated LlamaPi with Llama-3.2 3B as its default local LLM.
&lt;/p&gt;

&lt;p&gt;
Similar to Llama-3.1, I need to convert the model into gguf format, and then quantize it into different sizes. For 5-bit quantization, memory usage was reduced to ~2.7GB and generation speed reached 3.3 tokens/second. Compared to Llama-3.1 8B (4-bit quantized), the speedup is 1.83x.
&lt;/p&gt;

&lt;p&gt;
Here is a comparison using llama.cpp CLI:
&lt;/p&gt;

&lt;table border=&#34;2&#34; cellspacing=&#34;0&#34; cellpadding=&#34;6&#34; rules=&#34;groups&#34; frame=&#34;hsides&#34;&gt;


&lt;colgroup&gt;
&lt;col  class=&#34;org-left&#34; /&gt;

&lt;col  class=&#34;org-right&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-left&#34;&gt;&amp;#xa0;&lt;/th&gt;
&lt;th scope=&#34;col&#34; class=&#34;org-right&#34;&gt;tokens/second&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&#34;org-left&#34;&gt;Llama-3.1 8B (4-bit quantized)&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;1.8&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-left&#34;&gt;Llama-3.2 3B (8-bit quantized)&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;2.5&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td class=&#34;org-left&#34;&gt;Llama-3.2 3B (5-bit quantized)&lt;/td&gt;
&lt;td class=&#34;org-right&#34;&gt;3.3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
Generation quality seemed to be similar as Llama-3.1 8B, but I haven&#39;t had time to compare them extensively yet.
&lt;/p&gt;</description>
    </item>
    <item>
      <title>LlamaPi Robot - Voice chatbot with LLM and robot arm</title>
      <link>/notes/20240920_llamapi/</link>
      <pubDate>Fri, 20 Sep 2024 00:00:00 +0000</pubDate>
      <guid>/notes/20240920_llamapi/</guid>
      <description>&lt;div id=&#34;outline-container-org6931315&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org6931315&#34;&gt;Intro&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org6931315&#34;&gt;
&lt;p&gt;
Recently I built a prototype demonstrating the possibilities of &lt;b&gt;&lt;b&gt;Voice + LLM + Robotics&lt;/b&gt;&lt;/b&gt;. It is a voice chatbot running on Raspberry Pi 5 backed by the latest LLM (e.g. Llama-3.1), allowing the user to control robot arm gestures through voice interactions.
&lt;/p&gt;

&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;Backed by local LLM (Llama-3.1 8B) or cloud-based LLM.&lt;/li&gt;
&lt;li&gt;Local ASR (&lt;code&gt;faster_whisper&lt;/code&gt;) and TTS (&lt;code&gt;piper&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Robot arm commands generated by LLM based on the context of the conversation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
The prototype won 1st and 3nd prizes at the recent &lt;a href=&#34;https://lf-edge.atlassian.net/wiki/spaces/IA/pages/28311564/Day0+Hackathon#Results&#34;&gt;InfiniEdge AI Hackathon&lt;/a&gt;.
&lt;/p&gt;</description>
    </item>
    <item>
      <title>[论文解读] DistServe分离式架构优化大模型推理服务性能</title>
      <link>/notes/20240505_distserve_inference/</link>
      <pubDate>Sun, 05 May 2024 00:00:00 +0000</pubDate>
      <guid>/notes/20240505_distserve_inference/</guid>
      <description>&lt;p&gt;
这是一篇北大和UCSD合作的论文，主题是优化大模型推理服务的性能。
&lt;/p&gt;

&lt;p&gt;
在前文（RWKV）中提到过，对于大语言模型（LLM）来说，更大的挑战是推理。因为推理成本属于OpEx，用户使用越多，花费就越大。降低LLM的推理服务成本，是LLM应用在商业上可持续的关键之一。
&lt;/p&gt;

&lt;p&gt;
LLM推理服务对性能的要求，也与训练有所不同。推理服务更注重响应的延迟，由于直接面向用户，响应延迟直接影响用户体验。例如对于聊天机器人类型的应用，需要尽快的开始回答，也就是说要尽快生成输出第一个token，之后的token，需要能跟上人的阅读速度；而对于代码生成类的应用，则需要更快的端到端生成速度，以支持实时的代码提示。
&lt;/p&gt;

&lt;p&gt;
目前的大模型推理服务系统，都是以吞吐（throughput）为标准来优化的，也就是单位时间服务的用户请求数（request per second, rps）。这个指标，也被用作推理成本优化的一个目标，因为更高的吞吐，意味着可以用更少的GPU时间服务更多的用户请求。
&lt;/p&gt;

&lt;p&gt;
作者提出，简单的用吞吐作为指标是不够的。在实际场景中，应用对推理服务有不同的质量目标（service level objectives, SLO），对于LLM推理服务而言，最重要的有两个SLO：
&lt;/p&gt;

&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;TTFT (Time To First Token): LLM生成第一个token需要的时间&lt;/li&gt;
&lt;li&gt;TPOT (Time Per Output Token): LLM生成两个token之间的平均延迟&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
显然，TTFT表示LLM多久开始回答，而TPOT表示LLM的语速。
&lt;/p&gt;

&lt;p&gt;
作者认为，LLM推理服务的质量应该看Goodput，可以理解为“有效吞吐”。Goodput的意思是：
对于每个分配的GPU，在满足SLO目标的前提下（例如 90% TTFT &amp;lt; 200ms，90% TPOT &amp;lt; 50ms），所能达到的最大吞吐。更高的Goodput，意味着每个请求的服务成本更低。
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
maximum request rate that can be served adhering to the SLO attainment goal (say, 90%) for each GPU provisioned – higher per-GPU goodput directly translates into lower cost per query.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
更高的throughput，并不一定意味着更高的goodput。
&lt;/p&gt;


&lt;div id=&#34;orgf82aff6&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2024/20240505-162112_screenshot.png&#34; alt=&#34;20240505-162112_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
为什么生成第一个token会花费更久呢？
&lt;/p&gt;

&lt;p&gt;
因为在服务用户的时候，LLM需要把用户的历史对话作为上下文，加上用户当前的问题（请求），作为prompt去推理，因此生成第一个token需要计算很长的prompt。而后续的token，因为LLM推理普遍采用KV cache缓存前一次生成的中间结果，避免重复计算，每次生成token计算量要比第一个token小得多。
&lt;/p&gt;

&lt;p&gt;
关于KV cache，简单说几句：不要把它混淆为Key Value，这里的KV指的是Transformer的K，V矩阵。KV cache的原理是，自回归的LLM在生成时，每次生成的上下文，和上一次生成只差一个token，因此有大量计算是重复的。如果把上一次生成时的中间结果（主要是K，V矩阵）记下来，那么下一次生成的时候就可以避免重复计算，大大降低推理成本。这个技术目前已经是标配了，基本上所有的LLM推理都会用到它。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>谨慎使用C语言里的联合(union)和位域(bit field)！</title>
      <link>/notes/20240121_c_union_bitfield/</link>
      <pubDate>Sun, 21 Jan 2024 00:00:00 +0000</pubDate>
      <guid>/notes/20240121_c_union_bitfield/</guid>
      <description>&lt;p&gt;
对于内核、驱动、嵌入式系统等底层开发来说，C语言的bit field（位域）和union（联合）都是常用的特性。
位域可以让我们在结构体中指定某些成员占多少位，这在同硬件打交道的时候特别有用。例如硬件要求某个32位的消息里，第31位是flag，其余是value，用位域定义的数据结构：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-c++&#34;&gt;&lt;span style=&#34;font-weight: bold;&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;msg_t&lt;/span&gt; {
&amp;#8203;
  &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;uint32_t&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;flag&lt;/span&gt; : 1;
  &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;uint32_t&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;value&lt;/span&gt; : 31;
} &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;msg_t&lt;/span&gt;;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
在程序里可以直接操作结构体成员那样访问flag和value，而不用手动去对32位消息进行位操作，这些编译器都给我们做了。
我们还可以加上联合（union），使得我们既可以访问里面的成员，也可以按照一个32位数访问整个消息：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-c++&#34;&gt;&lt;span style=&#34;font-weight: bold;&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;msg_fields_t&lt;/span&gt; {
  &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;uint32_t&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;flag&lt;/span&gt; : 1;
  &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;uint32_t&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;value&lt;/span&gt; : 31;
} &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;msg_fields_t&lt;/span&gt;;
&amp;#8203;
&lt;span style=&#34;font-weight: bold;&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;msg_t&lt;/span&gt; {
  &lt;span style=&#34;font-weight: bold;&#34;&gt;union&lt;/span&gt; {
    &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;uint32_t&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;raw&lt;/span&gt;;
    &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;msg_fields_t&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;fields&lt;/span&gt;;
  };
} &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;msg_t&lt;/span&gt;;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
union告诉编译器，raw和fields这两个成员在结构体里占用同样的内存地址。因为这两个成员都是32位，因此raw就是整个32位的消息，而通过fields可以访问该消息的flags和value。
但是，在同时使用union和bit field的时候要注意，union和bit field如果互相套在一起，编译器产生的内存排列可能和你想的不一样！
&lt;/p&gt;</description>
    </item>
    <item>
      <title>My Little Reflections on Optane</title>
      <link>/notes/20231210_my_reflections_on_optane/</link>
      <pubDate>Sun, 10 Dec 2023 00:00:00 +0000</pubDate>
      <guid>/notes/20231210_my_reflections_on_optane/</guid>
      <description>&lt;p&gt;
In early 2023, Intel &lt;a href=&#34;https://www.intel.com/content/www/us/en/support/articles/000091826/../memory-and-storage/&#34;&gt;announced the discontinuity of Optane products&lt;/a&gt; (including SSD and memory). While not quite surprising considering their business environment, it’s still a bit of disappointment to me. As we are closing to the end of 2023, I decided to take some time and write down some of my reflections on Optane’s journey.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;[Disclaimer]&lt;/b&gt; All contents &amp;amp; discussions in this article are just my personal opinions and do not represent any organization or institution.
&lt;/p&gt;</description>
    </item>
    <item>
      <title>三国GPT (SanGuo GPT)  v0.1</title>
      <link>/notes/20230924_sanguo_gpt_v0.1/</link>
      <pubDate>Sun, 24 Sep 2023 00:00:00 +0000</pubDate>
      <guid>/notes/20230924_sanguo_gpt_v0.1/</guid>
      <description>&lt;div id=&#34;outline-container-orgfe6ce49&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgfe6ce49&#34;&gt;Overview&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgfe6ce49&#34;&gt;
&lt;p&gt;
SanGuo GPT is a Large Language Model trained on 三国演义 (San1 Guo2 Yan3 Yi4, Romance of the Three Kindoms), an ancient Chinese novel based on historical events happened ~1800 years ago during the late Han dynasty. It is a Transformer-based model with about 13.778M parameters in current version.
&lt;/p&gt;

&lt;p&gt;
I created this project for learning and exploration purpose.
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;I&#39;d like to try out the LLM application building process end-to-end, including major steps like data ingestion &amp;amp; preprocessing, shuffling/sampling, model building &amp;amp; training, visualization, model checkpointing and model serving.&lt;/li&gt;
&lt;li&gt;I want to explore the idea of &#34;书读千遍，其义自现&#34; (something like &#34;if you read a book a thousand times, the meaning and implications will emerge by itself&#34;). This idea popped up when I chat with a friend, and I found it very interesting. What if I train the model with data from just one book and iterate many steps? How would the model behave after intensive training on a single book?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
I also plan to use this project as a vehicle for playing with other new ideas - stay tuned!
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Some Math Notes About Self-Attention</title>
      <link>/notes/20230729_math_notes_self_attention/</link>
      <pubDate>Sat, 29 Jul 2023 00:00:00 +0000</pubDate>
      <guid>/notes/20230729_math_notes_self_attention/</guid>
      <description>&lt;p&gt;
If you are familiar with the recent frenzy about &lt;a href=&#34;https://chat.openai.com&#34;&gt;ChatGPT&lt;/a&gt;, &lt;a href=&#34;https://bard.google.com&#34;&gt;Bard&lt;/a&gt; and other large language models, you probably already know about &lt;a href=&#34;https://arxiv.org/abs/1706.03762&#34;&gt;Transformer&lt;/a&gt;, the key building block behind these models.
&lt;/p&gt;

&lt;p&gt;
The key algorithm inside Transformer block is &lt;a href=&#34;https://en.wikipedia.org/wiki/Self-attention&#34;&gt;Self Attention&lt;/a&gt;, which is commonly described as the following equation:
&lt;/p&gt;

\begin{matrix}
Attn(Q, K, V) = softmax(QK^T)V
\end{matrix}

&lt;p&gt;
(NOTE: the scaling part in the softmax is omitted for brevity.)
&lt;/p&gt;

&lt;p&gt;
Sometimes this equation is also written in an iterative way like this:
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Google AIGC开发平台MakerSuite - 用MakerSuite构建聊天机器人</title>
      <link>/notes/20230715_google_makersuite_chatbot/</link>
      <pubDate>Sat, 15 Jul 2023 00:00:00 +0000</pubDate>
      <guid>/notes/20230715_google_makersuite_chatbot/</guid>
      <description>&lt;div id=&#34;outline-container-org5aa4f2d&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org5aa4f2d&#34;&gt;MakerSuite 介绍&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org5aa4f2d&#34;&gt;
&lt;p&gt;
Google 在推出 PaLM 大语言模型和 Bard 聊天机器人之后，很快就推出了面向开发者的 MakerSuite，这是一个基于浏览器的云端 IDE，可以帮助用户快速试验大模型，以及开发 AIGC 应用原型。今天我们就来以聊天机器人为例，试验一下 MakerSuite 的开发体验。
&lt;/p&gt;

&lt;p&gt;
MakerSuite 的整个开发流程和 OpenAI 类似，先是在平台上试验提示，然后将试验结果导出成代码，变成可部署的产品。
&lt;/p&gt;

&lt;p&gt;
MakerSuite 目前支持 3 种场景：
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;Text prompt：最通用的一种，自由测试 PaLM 的各种提示&lt;/li&gt;
&lt;li&gt;Data prompt：将提示样本组织成表格形式&lt;/li&gt;
&lt;li&gt;Chat prompt：用于交互式聊天的模板&lt;/li&gt;
&lt;/ul&gt;


&lt;div id=&#34;org80438cc&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2023/20230716-144105_screenshot.png&#34; alt=&#34;20230716-144105_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;


&lt;div id=&#34;outline-container-org8ba3fe5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org8ba3fe5&#34;&gt;用 MakerSuite 构建聊天机器人&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org8ba3fe5&#34;&gt;
&lt;p&gt;
在主界面中选择“Chat Prompt”，创建一个新的聊天提示。
&lt;/p&gt;


&lt;div id=&#34;orgf357d0d&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2023/20230716-144230_screenshot.png&#34; alt=&#34;20230716-144230_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;
PaLM 提供的是通用的语言模型，而 Bard 则是基于 PaLM 构建的通用聊天机器人。而在实际应用中，我们经常会需要根据自己的需要构建定制化的聊天机器人，例如希望机器人以某个角色（e.g. 客服，老师）或某种风格（e.g. 亲切，专业）同用户交谈。这样的需求，可以在通用语言模型的基础上，通过小样本学习（few-shot prompting）来实现。
&lt;/p&gt;

&lt;p&gt;
首先我们要提供一些样本（Example），每个样本包含用户输入（提问）和模型的回答，在上下文（context）中告诉模型自己在对话中的角色和风格。这样通过上下文和少量的样本，PaLM 就能以期望的方式同用户交谈。
&lt;/p&gt;

&lt;p&gt;
假设我们想要构建的聊天机器人叫做 Amy，是一只生活在欧罗巴（木星的卫星之一）上的外星猫，聊天的对象是 K-12 的小朋友。
&lt;/p&gt;

&lt;p&gt;
在左边的 prompt example 里输入 context 和样本：
&lt;/p&gt;

&lt;pre class=&#34;example&#34; id=&#34;org6e467b2&#34;&gt;
Context: Your name is Amy, a friendly cat that lives on
Europa, one of Jupiter&#39;s moons.

User: Hello

Model: Hi! This is Amy the cat, I live on Europa, one of
Jupiter&#39;s moons. It&#39;s cold down here!
&lt;/pre&gt;

&lt;p&gt;
然后在右边测试一个提问：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>颠覆Transformer？新语言模型算法RWKV解读</title>
      <link>/notes/20230701_rwkv_paper/</link>
      <pubDate>Sat, 01 Jul 2023 00:00:00 +0000</pubDate>
      <guid>/notes/20230701_rwkv_paper/</guid>
      <description>&lt;p&gt;
RWKV 是 Peng Bo 提出的一个新的语言模型算法，它融合了 Transformer 和 RNN 的优点，在训练时能够像 Transformer 那样并行计算，又能在推理时像 RNN 那样高效，因此在 2022 年项目开源后热度迅速上升，吸引了全球众多开发者的参与。本文基于 RWKV 论文，讨论一下这个算法的原理，以及它为什么能够融合两者的优点。
&lt;/p&gt;


&lt;div id=&#34;org532e23d&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2023/20230707-171611_screenshot.png&#34; alt=&#34;20230707-171611_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
先看看 RWKV 的效果。
&lt;/p&gt;

&lt;p&gt;
RWKV 聊天：
&lt;/p&gt;

&lt;p width=&#34;800px&#34;&gt;
&lt;img src=&#34;../images/2023/20230707-173422_screenshot.png&#34; alt=&#34;20230707-173422_screenshot.png&#34; width=&#34;800px&#34; /&gt;
(图源：&lt;a href=&#34;https://github.com/BlinkDL/ChatRWKV&#34;&gt;https://github.com/BlinkDL/ChatRWKV&lt;/a&gt;)
&lt;/p&gt;

&lt;p&gt;
RWKV 文本生成的效果：
&lt;/p&gt;

&lt;p width=&#34;640px&#34;&gt;
&lt;img src=&#34;../images/2023/20230707-173735_screenshot.png&#34; alt=&#34;20230707-173735_screenshot.png&#34; width=&#34;640px&#34; /&gt;
(图源：&lt;a href=&#34;https://zhuanlan.zhihu.com/p/619721229&#34;&gt;https://zhuanlan.zhihu.com/p/619721229&lt;/a&gt;)
&lt;/p&gt;

&lt;p&gt;
RWKV 代码生成的效果：
&lt;/p&gt;

&lt;p width=&#34;640px&#34;&gt;
&lt;img src=&#34;../images/2023/20230707-173919_screenshot.png&#34; alt=&#34;20230707-173919_screenshot.png&#34; width=&#34;640px&#34; /&gt;
(图源：&lt;a href=&#34;https://zhuanlan.zhihu.com/p/619721229&#34;&gt;https://zhuanlan.zhihu.com/p/619721229&lt;/a&gt;)
&lt;/p&gt;

&lt;p&gt;
顺便提一句，RWKV 的作者 Peng Bo 也是一位神人，大家有兴趣可以关注一下这位的 Zhihu。
&lt;/p&gt;

&lt;div id=&#34;outline-container-orgb12f434&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgb12f434&#34;&gt;1. 一些背景&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgb12f434&#34;&gt;
&lt;p&gt;
最近以 GPT 为代表的大语言模型（LLM）的爆火，让 Transformer 这个算法广为人知。这个源自 2017 年「Attention Is All You Need」论文的算法，是几乎所有大模型的基础，GPT 里的 T 就是 Transformer。可以说正是 Transformer 算法造就了现在的 AIGC 的大突破。
&lt;/p&gt;

&lt;p&gt;
Transformer 的成功，我认为关键是两点：一是 Transformer 的注意力机制，对 token 之间关系的建模表达能力极强；二是 Transformer 算法训练时可以并行。
&lt;/p&gt;

&lt;p&gt;
在 Transformer 之前，语言建模的主流是 RNN/LSTM。Transformer 里的注意力机制，其概念实际上在 RNN/LSTM 时期就提出来了，但 RNN 的一个致命弱点就是训练很难并行，导致训练效率太低，很大程度上限制了模型规模。因此 Transformer 出现后，不仅在自然语言理解领域迅速占领了原本 RNN/LSTM 模型的份额，还扩展到了视觉等其他领域。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>超长上下文&#43;无分词器，新一代大模型架构？Meta最新论文MegaByte解读</title>
      <link>/notes/20230604_megabyte_llm/</link>
      <pubDate>Sat, 10 Jun 2023 00:00:00 +0000</pubDate>
      <guid>/notes/20230604_megabyte_llm/</guid>
      <description>&lt;p&gt;
今天来解读一下 Meta 的这篇论文：MEGABYTE: Predicting Million-byte Sequences with Multiscale Transformers
&lt;/p&gt;

&lt;div id=&#34;outline-container-org6da917f&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org6da917f&#34;&gt;大模型的上下文窗口瓶颈&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org6da917f&#34;&gt;
&lt;p&gt;
基于 Transformer  的大语言模型，有个很重要的指标就是上下文长度。这是因为模型本身是无状态的，它在推理时只能“记住”上下文窗口里的内容。因此我们在和模型对话时，需要把对话的历史（上下文）和我们的提示一起发给模型，否则模型就只能看到提示本身。随着对话的进行，这个上下文会越来越长，当超过模型的上下文窗口长度时，模型就只能“忘记”最早的对话内容了。
&lt;/p&gt;

&lt;p&gt;
例如在下面这个会话里，如果我们把上下文窗口的长度设为 10 个 token，可以看到模型就不能记住之前对话的内容了：
&lt;/p&gt;

&lt;pre class=&#34;example&#34; id=&#34;org439d9bf&#34;&gt;
User&amp;gt; Hi, my name is Ping
AI&amp;gt; Hello Ping, it&#39;s nice to meet you! My name is OpenAI.
    How can I assist you today?

User&amp;gt; What is 1+1?
AI&amp;gt; The answer to 1+1 is 2.

User&amp;gt; What is my name?
AI&amp;gt; I&#39;m sorry, I don&#39;t have access to that information.
    Could you please tell me your name?
&lt;/pre&gt;

&lt;p&gt;
上面这个例子只是文本对话，对于多模态大模型而言（例如视觉大模型），输入的序列长度可以达到几百万个 token，因此上下文长度对于多模态大模型有极其重要的意义。但是，目前基于 Transformer 的大模型，普遍都只支持几千个 token 的上下文长度。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Variable Length Array in C&#43;&#43;</title>
      <link>/notes/20230423_cpp_variable_length_array/</link>
      <pubDate>Sun, 23 Apr 2023 00:00:00 +0000</pubDate>
      <guid>/notes/20230423_cpp_variable_length_array/</guid>
      <description>&lt;p&gt;
经常用 C/C++的朋友都知道，C/C++里面声明变量或者数组，是由编译器在编译时分配在堆栈上的，例如这个例子：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-c++&#34;&gt;&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;main&lt;/span&gt;() {
    &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;a&lt;/span&gt;;          &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#22768;&amp;#26126;&amp;#19968;&amp;#20010;&amp;#21464;&amp;#37327;
&lt;/span&gt;    &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;arr&lt;/span&gt;[10];    &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#22768;&amp;#26126;&amp;#19968;&amp;#20010;&amp;#25968;&amp;#32452;
&lt;/span&gt;
    &lt;span style=&#34;font-weight: bold;&#34;&gt;return&lt;/span&gt; 0;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这个例子里的变量 &lt;code&gt;a&lt;/code&gt; 和数组 &lt;code&gt;arr&lt;/code&gt; 都是在编译时在栈上已经分配好了空间，这个和我们用 &lt;code&gt;malloc()&lt;/code&gt;, &lt;code&gt;new&lt;/code&gt; 在运行时分配空间不同，后者是分配在堆(heap)上。
&lt;/p&gt;

&lt;p&gt;
因为这些声明的变量/数组是在编译时分配的，它们的大小必须在编译时就已知，也就是说不能在运行时才决定数组的大小：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-c++&#34;&gt;&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;r&lt;/span&gt; = 1 + (rand() % 10);

&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;arr&lt;/span&gt;[r]; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;C++&amp;#35821;&amp;#35328;&amp;#19981;&amp;#20801;&amp;#35768;&amp;#36825;&amp;#20040;&amp;#22768;&amp;#26126;&amp;#65292;&amp;#22240;&amp;#20026;r&amp;#32534;&amp;#35793;&amp;#26102;&amp;#26410;&amp;#30693;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;
但是最近用 C++的时候注意到一个神奇的事情，像上面这样不符合 C++语言规范的用法，也能编译通过并正常运行！例如：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>关于 =decltype，remove_pointer= ，别名和函数指针类型</title>
      <link>/notes/20221112_decltype_func_ptrs/</link>
      <pubDate>Sat, 12 Nov 2022 00:00:00 +0000</pubDate>
      <guid>/notes/20221112_decltype_func_ptrs/</guid>
      <description>&lt;p&gt;
C++里的 &lt;code&gt;decltype&lt;/code&gt; 是个神奇的存在，你给它一个名字或表达式，它会返回这个名字或表达式的类型。并且这个检查是在编译时进行的，所以你给它的表达式不会真的运行，而只是用作类型推导，例如：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-c++&#34;&gt;&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;f&lt;/span&gt;();
&lt;span style=&#34;font-weight: bold;&#34;&gt;decltype&lt;/span&gt;(f()) &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;a&lt;/span&gt;;  &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;a is bool&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
这里 &lt;code&gt;decltype&lt;/code&gt; 在编译时用 &lt;code&gt;f()&lt;/code&gt; 推导出类型 bool（因为函数 f 返回 bool），但实际运行时并不会真的执行这个 &lt;code&gt;f()&lt;/code&gt; 。
&lt;/p&gt;

&lt;p&gt;
大部分时间， &lt;code&gt;decltype&lt;/code&gt; 都能返回你想要的结果。
&lt;/p&gt;

&lt;p&gt;
但是遇到别名和函数指针类型，情况就会绕一些，咱们分别讨论一下。
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-c++&#34;&gt;&lt;span style=&#34;font-weight: bold;&#34;&gt;using&lt;/span&gt; &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;II&lt;/span&gt; = &lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;int&lt;/span&gt;* ();
&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;This is equivalent to declaring an external function (not a pointer):
&lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;extern int* a1();
&lt;/span&gt;&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;II&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;a1&lt;/span&gt;;
&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;This will cause compile error unless a function int* a1() is implemented.
&lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;a1();&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
类型别名 &lt;code&gt;II&lt;/code&gt; 是一个返回 &lt;code&gt;int*&lt;/code&gt; 的函数类型（注意，不是函数指针哈）。于是用 &lt;code&gt;II&lt;/code&gt; 声明的 &lt;code&gt;a1&lt;/code&gt; 就是一个返回 &lt;code&gt;int*&lt;/code&gt; 的函数。但是这里只是申明了函数 &lt;code&gt;a1&lt;/code&gt; 而已，并没有它的实现，所以调用 &lt;code&gt;a1&lt;/code&gt; 是会编译出错的。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Emacs里如何把某个字符替换为“换行”？</title>
      <link>/notes/20220904_emacs_replace_with_newline/</link>
      <pubDate>Sun, 04 Sep 2022 00:00:00 +0000</pubDate>
      <guid>/notes/20220904_emacs_replace_with_newline/</guid>
      <description>&lt;p&gt;
Emacs 的 &lt;code&gt;query-replace&lt;/code&gt; 是一个很常用的查找替换命令（快捷键 &lt;code&gt;M-%&lt;/code&gt; ）。这个命令会提示你输入要查找的字符串，再输入要替换的字符串，然后就会从当前位置逐个查找和确认是否替换。
&lt;/p&gt;

&lt;p&gt;
但是，如果我想要把某个字符替换为特殊字符，例如想把字符“;”替换为“换行”，就不能直接输入了，因为如果你在第二步输入了回车，它会认为你想要把查找的字符串替换为空字符串（相当于查找＋删除）。怎么办呢？
&lt;/p&gt;

&lt;p&gt;
查了一下，有这样几个办法。
&lt;/p&gt;

&lt;p&gt;
一是在输入要替换的字符串时，输入 &lt;code&gt;C-q C-j&lt;/code&gt; ，然后回车。
&lt;/p&gt;


&lt;div id=&#34;org23650bb&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2022/20220904_emacs_replace_newline1.png&#34; alt=&#34;20220904_emacs_replace_newline1.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
这里的 &lt;code&gt;C-q&lt;/code&gt; 表示 &lt;code&gt;quoted-insert&lt;/code&gt; ，意思是告诉 Emacs 输入后面的控制字符。而 &lt;code&gt;C-j&lt;/code&gt; 代表的是 ASCII 码 0x0a，也就是 newline。然后按下回车，就会用 ASCII 码 0x0a 来替换字符串“;”。
&lt;/p&gt;


&lt;div id=&#34;org81cbcb1&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2022/20220904_emacs_replace_newline2.png&#34; alt=&#34;20220904_emacs_replace_newline2.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
还有种方法，就是在 &lt;code&gt;C-q&lt;/code&gt; 之后输入 ASCII 码的八进制数，例如 0x0a 的八进制数就是 12 。
&lt;/p&gt;

&lt;p&gt;
另一种办法可能更直观，就是用 &lt;code&gt;C-k&lt;/code&gt; 去删除一个空行，把空行加入到 kill-ring 里，然后在输入要替换的字符串时，用 &lt;code&gt;C-y&lt;/code&gt; 把它粘贴进来。这个就有点类似图形界面编辑器（例如VSCode）里的操作了。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Emacs集成开发环境和远程开发配置</title>
      <link>/notes/20220814_emacs_remote_development/</link>
      <pubDate>Sun, 14 Aug 2022 00:00:00 +0000</pubDate>
      <guid>/notes/20220814_emacs_remote_development/</guid>
      <description>&lt;p&gt;
一个经典问题，如何把 Emacs 配置出 IDE 的效果？
&lt;/p&gt;

&lt;p&gt;
对于本地开发来说，可以用 projectile+lsp 配合相应语言的 language server（例如 C++的 clangd），基本上就能满足需要。
&lt;/p&gt;

&lt;p&gt;
如果 clangd 不够智能，例如有些头文件或者符号找不到，可以用 &lt;code&gt;compile_commands.json&lt;/code&gt; 文件来指导 clangd。 &lt;code&gt;compile_commands.json&lt;/code&gt; 文件，你可以把它理解为编译时产生的 trace，记录了整个 project 的编译步骤，通过它 clangd 就能知道每个文件是如何编译的，包括头文件在哪里，链接库在哪里，乃至各个符号的定义等。有了这个，你的 Emacs 基本上就具备了集成开发环境的主要能力。
&lt;/p&gt;

&lt;p&gt;
如何生成 &lt;code&gt;compile_commands.json&lt;/code&gt; 文件呢？取决于项目的构建工具。如果是 cmake，ninja 等比较现代的工具，都内置了导出 &lt;code&gt;compile_commands.json&lt;/code&gt; 文件的功能，比如 cmake 里只要加上这个环境变量就行了：
&lt;/p&gt;

&lt;pre class=&#34;example&#34; id=&#34;org464fd46&#34;&gt;
CMAKE_EXPORT_COMPILE_COMMANDS
&lt;/pre&gt;

&lt;p&gt;
如果工具不支持自动导出 &lt;code&gt;compile_commands.json&lt;/code&gt; ，可以在编译时用 bear 来记录。bear 相当于一个命令的 wrapper，后面的参数就是你的编译命令。例如：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-shell&#34;&gt;./configure
bear make
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;code&gt;bear&lt;/code&gt; 会把 &lt;code&gt;make&lt;/code&gt; 过程中执行的步骤全都记录在 &lt;code&gt;compile_commands.json&lt;/code&gt; 里。
&lt;/p&gt;

&lt;p&gt;
但是还有个问题：如果项目代码在远程机器上呢？Emacs 能否有类似 VSCode 的远程开发能力？
&lt;/p&gt;

&lt;p&gt;
答案是可以的，但是需要你自己配置。:-)
&lt;/p&gt;

&lt;p&gt;
Emacs 内置有远程连接的客户端 tramp，支持 SSH 等多种连接方式。我们可以通过 tramp 来访问远程机器上的文件。例如我们在打开文件时输入这样的地址：
&lt;/p&gt;

&lt;pre class=&#34;example&#34; id=&#34;orgf6b059c&#34;&gt;
/ssh:user@192.168.0.100#1234:/home/user/test.c
&lt;/pre&gt;

&lt;p&gt;
这个地址告诉 tramp，我们用 ssh 方式打开主机 192.168.0.100 上的文件 &lt;code&gt;/home/user/test.c&lt;/code&gt; ，登录用户名 user，连接端口是 1234 (如果 ssh 用的是默认配置，端口可以省略)。如果需要，tramp 会提示你输入密码登录。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>用Emacs做PPT演示</title>
      <link>/notes/20220709_emacs_presentation/</link>
      <pubDate>Sat, 09 Jul 2022 00:00:00 +0000</pubDate>
      <guid>/notes/20220709_emacs_presentation/</guid>
      <description>&lt;div id=&#34;org5879a3d&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2022/2022-07-09_10-56-47_screenshot.png&#34; alt=&#34;2022-07-09_10-56-47_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgac9fef4&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgac9fef4&#34;&gt;为什么要用 Emacs 做 PPT 演示&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgac9fef4&#34;&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;我也不知道为啥，看起来酷呗 :-)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
按照大佬的说法：
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;不需要复杂的 presentation 软件&lt;/li&gt;
&lt;li&gt;可以让你专注在演讲的内容上&lt;/li&gt;
&lt;li&gt;给你的同事留下牛 X 的印象
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;当然，也可能把他们搞糊涂 :-)&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgbfa7de2&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgbfa7de2&#34;&gt;安装 org-present 包&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgbfa7de2&#34;&gt;
&lt;p&gt;
如果是 Doom Emacs，它已经自带了 org-present 支持，只需要打开即可。打开 &lt;code&gt;.doom.d/init.el&lt;/code&gt; ，在 org 那栏加上 present 即可：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-emacs-lisp&#34;&gt;(doom! &lt;span style=&#34;font-weight: bold;&#34;&gt;:input&lt;/span&gt;
       &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;......
&lt;/span&gt;       &lt;span style=&#34;font-weight: bold;&#34;&gt;:lang&lt;/span&gt;
       &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;......
&lt;/span&gt;       (org                &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;organize your plain life in plain text
&lt;/span&gt;        &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;......
&lt;/span&gt;        +present
        +pretty
        +roam2)
       &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;;; &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;......&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
如果是用自己的配置，用 use-package 或者手动安装即可。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Doom Emacs中文字体显示问题的解决</title>
      <link>/notes/20220703_chinese_display_in_doom_emacs/</link>
      <pubDate>Sun, 03 Jul 2022 00:00:00 +0000</pubDate>
      <guid>/notes/20220703_chinese_display_in_doom_emacs/</guid>
      <description>&lt;div id=&#34;outline-container-org538572c&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org538572c&#34;&gt;问题&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org538572c&#34;&gt;
&lt;p&gt;
Doom Emacs 别的都挺好，就是有个奇怪的小问题，在显示中文的时候，会出现下面这样字体不一致的情况：
&lt;/p&gt;


&lt;div id=&#34;orgf6294a0&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2022/20220703_151615screenshot.png&#34; alt=&#34;20220703_151615screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
可以看到，同一行文字里的中文字符，它似乎用了不同的字体来显示，导致显示出来的文字大小样式不一，显得很奇怪。这种情况，我在以前的 Emacs 配置里没有遇到过，感觉似乎是 Doom 里某些编码没有指定字体？
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org0d266f9&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org0d266f9&#34;&gt;解决&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org0d266f9&#34;&gt;
&lt;p&gt;
开始我以为只是 org-mode 的问题，后来发现，这个问题在其他模式（例如代码注释）里也存在，因此是 Doom Emacs 本身的问题。
&lt;/p&gt;

&lt;p&gt;
经过一番研究，找到这个帖子：
&lt;a href=&#34;https://emacs.stackexchange.com/questions/63850/doom-emacs-how-to-align-chinese-characters-in-org-tables&#34;&gt;https://emacs.stackexchange.com/questions/63850/doom-emacs-how-to-align-chinese-characters-in-org-tables&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
这个帖子是关于 org-mode 表格显示的，但其中对中文字体的设置也有借鉴意义：我们可以用 &lt;code&gt;set-font-set&lt;/code&gt; 这个函数，对指定的字符集设置字体。
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-emacs-lisp&#34;&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;pz/setup-cjk-fonts&lt;/span&gt; ()
  (&lt;span style=&#34;font-weight: bold;&#34;&gt;interactive&lt;/span&gt;)
  (&lt;span style=&#34;font-weight: bold;&#34;&gt;if&lt;/span&gt; (display-graphic-p)
      (&lt;span style=&#34;font-weight: bold;&#34;&gt;dolist&lt;/span&gt; (charset &#39;(kana han cjk-misc bopomofo))
        (set-fontset-font (frame-parameter nil &#39;font)
                          charset (font-spec &lt;span style=&#34;font-weight: bold;&#34;&gt;:family&lt;/span&gt; &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;Noto Sans Mono CJK SC&#34;&lt;/span&gt;)))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;code&gt;set-font-set&lt;/code&gt; 函数的定义如下：
&lt;/p&gt;

&lt;pre class=&#34;example&#34; id=&#34;orgda66814&#34;&gt;
(set-fontset-font NAME TARGET FONT-SPEC &amp;amp;optional FRAME ADD)
&lt;/pre&gt;

&lt;p&gt;
第一个是要设置的窗口参数，我们用 &lt;code&gt;frame-parameter&lt;/code&gt; 加 nil 可以获取当前窗口的字体参数。然后对这个参数，设置各个字符集的字体。这里字符集参数 &lt;code&gt;charset&lt;/code&gt; ：
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;可以是字符集名称（例如 chinese-gbk，可以通过命令 &lt;code&gt;list-character-sets&lt;/code&gt; 查看）；&lt;/li&gt;
&lt;li&gt;也可以是 script symbol，可以查看变量 &lt;code&gt;script-representative-chars&lt;/code&gt; 获取所有的 script symbol 名字。&lt;/li&gt;
&lt;li&gt;也可以是单个字符，即为单个字符指定字体；&lt;/li&gt;
&lt;li&gt;如果是 nil，则表示给所有未设置字体的字符集设置字体。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
对我来说，就是给 CJK 字符集设置中文字体，这里用的是 script symbol，包括 kana, han, cjk-misc, bopomofo 这几个。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Doom Emacs on Ubuntu Linux 尝鲜</title>
      <link>/notes/20220521_doom_emacs_on_linux/</link>
      <pubDate>Sat, 21 May 2022 00:00:00 +0000</pubDate>
      <guid>/notes/20220521_doom_emacs_on_linux/</guid>
      <description>&lt;div id=&#34;outline-container-org55053f5&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org55053f5&#34;&gt;Doom Emacs简介&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org55053f5&#34;&gt;
&lt;p&gt;
Doom Emacs 是一个 Emacs 的配置框架，相比原厂的 Emacs 配置，Doom Emacs 提供了更方便完善的默认设置，预装了常用的包，并且提供了一个很容易自定义的框架。同时，Doom Emacs 启动速度也很快。最近在 Ubuntu 上试用了一下，感觉不错，正在考虑将我原有的配置移到 Doom Emacs 上去。
&lt;/p&gt;


&lt;div id=&#34;org05c8718&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2022/2022-05-21_19-14-11_screenshot.png&#34; alt=&#34;2022-05-21_19-14-11_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
注意，Doom Emacs 不是 Emacs 发行版，只是一组 Emacs 配置，你运行 Doom Emacs 时，运行的还是系统上安装的 Emacs。Doom Emacs 需要 Emacs 27.1 以上，如果你的 Emacs 版本太低，需要先升级才能使用。
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org88b34b8&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org88b34b8&#34;&gt;在 Ubuntu 上安装 Doom Emacs&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org88b34b8&#34;&gt;
&lt;p&gt;
首先你需要 Emacs 27.1 以上，个人推荐最新的 28.1 ，并带上 native-compilation 。
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-shell&#34;&gt;./configure --prefix=$&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;HOME&lt;/span&gt;/local &lt;span style=&#34;font-style: italic;&#34;&gt;\&lt;/span&gt;
            --with-native-compilation &lt;span style=&#34;font-style: italic;&#34;&gt;\&lt;/span&gt;
            --with-x --with-json &lt;span style=&#34;font-style: italic;&#34;&gt;\&lt;/span&gt;
            --with-jpeg --with-tiff --with-png
make -j4
make install
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
根据Doom Emacs的建议，加上 &lt;code&gt;--with-json&lt;/code&gt; 可以提高运行速度。安装完成后确保 &lt;code&gt;~/.local/bin&lt;/code&gt; 在PATH里。
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Paxos 讨论：Phase-1 收到更高的 proposal number 该怎么办?</title>
      <link>/notes/20220408_paxos_note_prepare_higher_proposal_number/</link>
      <pubDate>Fri, 08 Apr 2022 00:00:00 +0000</pubDate>
      <guid>/notes/20220408_paxos_note_prepare_higher_proposal_number/</guid>
      <description>&lt;p&gt;
最近研究了一下Paxos，这个协议本身并不难懂，但 Lamport 的文章比较抽象，在具体实现上有一些细节没有充分讨论到，这里就讨论其中之一。
&lt;/p&gt;

&lt;p&gt;
先聊一下背景：我们知道，每次运行Paxos（也就是一个Paxos实例，Paxos Instance）都由两个阶段（phase）组成。在phase-1，proposer 向 acceptor 发送 prepare 消息，并根据收到的回应决定是否可以进入下一阶段 phase-2 。
&lt;/p&gt;

&lt;p&gt;
这个prepare消息主要内容是 proposer 的 proposal number （有些地方也称为 ballot number），例如在 Lamport 的 &lt;a href=&#34;https://www.microsoft.com/en-us/research/publication/paxos-made-simple/&#34;&gt;Paxos Made Simple&lt;/a&gt; 文章里：
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
(a) A proposer selects a proposal number n and sends a prepare request with number n to a majority of acceptors.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
当一个 acceptor 收到这个 prepare 请求时，它会把这个 proposal number 与它之前见过（承诺过） 的值比较，如果小于它之前见过的，则拒绝这个 prepare 请求，否则就接受这个 proposal ，并承诺 (promise) 它不再接受比这个 proposal number 更小的 proposal 。同样还是 Lamport 的这篇文章：
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
(b) If an acceptor receives a prepare request with number n greater than that of any prepare request to which it has already responded, then it responds to the request with a promise not to accept any more proposals numbered less than n and with the highest-numbered proposal (if any) that it has accepted.
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Emacs 28.1  正式发布，elisp原生编译支持来了！</title>
      <link>/notes/20220404_emacs_28_1_released/</link>
      <pubDate>Mon, 04 Apr 2022 00:00:00 +0000</pubDate>
      <guid>/notes/20220404_emacs_28_1_released/</guid>
      <description>&lt;p&gt;
期待已久的 Emacs 28.1 版本来了！这个版本中引入了一系列新特性，其中最引人注目，也最受期待的恐怕就是对Emacs Lisp（elisp）的原生编译支持（native compilation）。
&lt;/p&gt;

&lt;p&gt;
目前 Emacs 28.1 还没有apk等二进制包，需要从源代码安装，方法和以前版本类似。但需要注意的是，原生elisp编译特性默认是不打开的，需要在 &lt;code&gt;configure&lt;/code&gt; 时候加上 &lt;code&gt;--with-native-compilation&lt;/code&gt; 参数。
&lt;/p&gt;

&lt;p&gt;
另外，这个特性还依赖 &lt;code&gt;libgccjit&lt;/code&gt; 和 &lt;code&gt;gcc-10&lt;/code&gt; 包，需要先安装这些依赖包，否则 &lt;code&gt;--with-native-compilation&lt;/code&gt; 参数会被拒绝：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-shell&#34;&gt;sudo apt install -y libgccjit0 libgccjit-10-dev gcc-10
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
安装完依赖包，就可以编译 Emacs 28.1 了：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-shell&#34;&gt;&lt;span style=&#34;font-weight: bold;&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;CC&lt;/span&gt;=&lt;span style=&#34;font-style: italic;&#34;&gt;&#34;gcc-10&#34;&lt;/span&gt;
./autogen.sh
./configure --prefix=$&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;HOME&lt;/span&gt;/local/ --with-imagemagick --with-native-compilation
make -j2
make install
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
安装完成！
&lt;/p&gt;


&lt;div id=&#34;org38ae954&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2022-04-04_14-26-54_screenshot.png&#34; alt=&#34;2022-04-04_14-26-54_screenshot.png&#34; width=&#34;640px&#34; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
试试看这个 native elisp compilation ，随便写个简单的 elisp 文件然后用 &lt;code&gt;native-compile&lt;/code&gt; 函数编译：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-emacs-lisp&#34;&gt;(native-compile &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;serve.el&#34;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
生成的原生二进制文件会保存在 &lt;code&gt;~/.emacs.d/eln-cache/&lt;/code&gt; 目录下。用 &lt;code&gt;file&lt;/code&gt; 命令查看，可以看到它被编译成了原生的ELF文件：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-shell&#34;&gt;file ~/.emacs.d/eln-cache/28.1-18b24ab0/serve-902d1548-7e0cb452.eln 
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre class=&#34;example&#34; id=&#34;orgb7241b1&#34;&gt;
.../serve-902d1548-7e0cb452.eln: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=92a81b6c71e5cfee84e9763d9ac0625a0164875c, not stripped
&lt;/pre&gt;

&lt;p&gt;
除了原生elisp编译外，Emacs 28.1 还有很多新特性，以后有空慢慢探索。 :-)
&lt;/p&gt;</description>
    </item>
    <item>
      <title>C&#43;&#43; vector容器强制释放内存</title>
      <link>/notes/20211127_cpp_container_force_free_memory/</link>
      <pubDate>Sat, 27 Nov 2021 00:00:00 +0000</pubDate>
      <guid>/notes/20211127_cpp_container_force_free_memory/</guid>
      <description>&lt;p&gt;
换个话题，聊聊使用C++ STL vector容器时的一个内存管理问题。
&lt;/p&gt;

&lt;p&gt;
C++用户经常会用STL里的vector容器来管理一组动态对象。STL vector的使用和C语言的数组类似，很方便：
&lt;/p&gt;
&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-c++&#34;&gt;&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;std&lt;/span&gt;::&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;vector&lt;/span&gt;&amp;lt;&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;int&lt;/span&gt;&amp;gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;buf&lt;/span&gt; = { 0, 1, 2, 3, 4, 5 };
buf[0]++;
buf[1] = 10;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
并且内存的使用和释放都由STL管理，用户不用像C语言那样手动malloc和free管理内存，确实省心不少。
&lt;/p&gt;

&lt;p&gt;
但是在有些情况下，我们需要对容器占用的内存进行手动管理。
&lt;/p&gt;

&lt;p&gt;
举个例子，假如我们有个数据管道，每次迭代生成一个样本池，里面有几百万个对象放在一个vector里，从中抽取一万个样本，然后交给管道作下一步处理，并且这个过程会反复进行。
&lt;/p&gt;

&lt;p&gt;
那么在这个反复迭代过程中，我们希望样本池在每次采样完后就从内存里释放掉。否则下一次迭代时，我们再次生成样本池，而前一次占用的内存的还没释放掉，就有可能因为内存不够导致程序崩溃（Out Of Memory）。
&lt;/p&gt;

&lt;p&gt;
你可能会问，这种情况用容器的clear方法不就好了？
&lt;/p&gt;

&lt;p&gt;
但是，clear方法只是把这个容器的size变成了0，如果它的capacity其实没变，也就是说，clear方法并没有真的释放容器占用的内存。
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-c++&#34;&gt;buf.clear();

&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; buf.size();      &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;size&amp;#21464;&amp;#25104;&amp;#20102;0
&lt;/span&gt;&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;std&lt;/span&gt;::cout &amp;lt;&amp;lt; buf.capacity();  &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;capacity&amp;#36824;&amp;#26159;6&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
那么在C++ STL里，是可以手动强制释放容器占用的内存的。方法不止一个，这里举个简单可靠的，就是用swap方法：
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-c++&#34;&gt;&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;std&lt;/span&gt;::&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;vector&lt;/span&gt;&amp;lt;&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;int&lt;/span&gt;&amp;gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;buf&lt;/span&gt; = { 0, 1, 2, 3, 4, 5 };
&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;......
&lt;/span&gt;
&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;&amp;#24378;&amp;#21046;&amp;#37322;&amp;#25918;buf&amp;#21344;&amp;#29992;&amp;#30340;&amp;#20869;&amp;#23384;
&lt;/span&gt;&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;std&lt;/span&gt;::vector&amp;lt;&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;int&lt;/span&gt;&amp;gt;().swap(buf);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
解释一下这个方法的原理：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Lisp里的延迟执行</title>
      <link>/notes/20210731_deferred_execution_lisp/</link>
      <pubDate>Sat, 31 Jul 2021 00:00:00 +0000</pubDate>
      <guid>/notes/20210731_deferred_execution_lisp/</guid>
      <description>&lt;p&gt;
在图计算和协程里经常会用到的“延迟执行”，在Lisp里，只需要十几行代码就能实现！
&lt;/p&gt;

&lt;div id=&#34;outline-container-org944b796&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org944b796&#34;&gt;创建和使用延迟执行对象&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org944b796&#34;&gt;
&lt;p&gt;
首先我们来定义一个宏 &lt;code&gt;defer&lt;/code&gt; ，它的作用是把输入的代码块变成一个延迟执行的对象（其实是一个闭包）：
&lt;/p&gt;
&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-lisp&#34;&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;defmacro&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;defer&lt;/span&gt; (&lt;span style=&#34;font-weight: bold; text-decoration: underline;&#34;&gt;&amp;amp;body&lt;/span&gt; body)
  (&lt;span style=&#34;font-weight: bold;&#34;&gt;let&lt;/span&gt; ((executed (gensym))
        (result (gensym)))
    `(&lt;span style=&#34;font-weight: bold;&#34;&gt;let&lt;/span&gt; ((,executed nil)
           (,result nil))
       (&lt;span style=&#34;font-weight: bold;&#34;&gt;lambda&lt;/span&gt; ()
         (&lt;span style=&#34;font-weight: bold;&#34;&gt;unless&lt;/span&gt; ,executed
           (setf ,result (&lt;span style=&#34;font-weight: bold;&#34;&gt;progn&lt;/span&gt; ,@body))
           (setf ,executed t))
         ,result))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
而如果要执行之前被推迟的代码，可以用这个函数：
&lt;/p&gt;
&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-lisp&#34;&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;font-weight: bold;&#34;&gt;defer-execute&lt;/span&gt; (deferred)
  (funcall deferred))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
例如，我们有这样一块代码：
&lt;/p&gt;
&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-lisp&#34;&gt;(princ &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;Hello, world.&#34;&lt;/span&gt;)
(princ (1+ 2))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
用 &lt;code&gt;defer&lt;/code&gt; 来包装它：
&lt;/p&gt;
&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-lisp&#34;&gt;(defer
  (princ &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;Hello, world.&#34;&lt;/span&gt;)
  (princ (1+ 2)))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;code&gt;defer&lt;/code&gt; 会把输入的代码块包装成一个 &lt;b&gt;闭包&lt;/b&gt; 返回给我们。所以通常我们要把这个闭包存在一个变量里：
&lt;/p&gt;
&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-lisp&#34;&gt;(&lt;span style=&#34;font-weight: bold;&#34;&gt;defvar&lt;/span&gt; &lt;span style=&#34;font-weight: bold; font-style: italic;&#34;&gt;*deferred-hello*&lt;/span&gt;
  (defer
    (princ &lt;span style=&#34;font-style: italic;&#34;&gt;&#34;Hello, world.&#34;&lt;/span&gt;)
    (princ (1+ 2))))
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
等我们想要执行这个代码块的时候，只需要用 &lt;code&gt;defer-execute&lt;/code&gt; 来调用这个闭包：
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Markdown in Emacs: Live Preview, Math and Images</title>
      <link>/notes/20201111_markdown_in_emacs_live_preview_math_and_images/</link>
      <pubDate>Wed, 11 Nov 2020 00:00:00 +0000</pubDate>
      <guid>/notes/20201111_markdown_in_emacs_live_preview_math_and_images/</guid>
      <description>&lt;div id=&#34;outline-container-orgf41bfed&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgf41bfed&#34;&gt;Introduction&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgf41bfed&#34;&gt;
&lt;p&gt;
Emacs has a Markdown mode, but I need a more comprehensive setup with features like:
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;Live preview window&lt;/li&gt;
&lt;li&gt;Rendering of math equations&lt;/li&gt;
&lt;li&gt;Rendering of local and remote images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Basically I need a setup that provides similar functionality as VS Code + Markdown extensions.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-orgef86f5f&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orgef86f5f&#34;&gt;Install dependencies&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orgef86f5f&#34;&gt;
&lt;p&gt;
Emacs packages needed:
&lt;/p&gt;
&lt;ul class=&#34;org-ul&#34;&gt;
&lt;li&gt;markdown-mode&lt;/li&gt;
&lt;li&gt;markdown-mode&lt;/li&gt;
&lt;li&gt;simple-httpd&lt;/li&gt;
&lt;li&gt;impatient-mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Install pandoc:
&lt;/p&gt;
&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-shell&#34;&gt;brew install pandoc
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
Get MathJax:
&lt;/p&gt;
&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-shell&#34;&gt;git clone https://github.com/mathjax/MathJax.git mathjax
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org7242e02&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org7242e02&#34;&gt;Configure Emacs&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org7242e02&#34;&gt;
&lt;/div&gt;
&lt;div id=&#34;outline-container-org8feef9b&#34; class=&#34;outline-3&#34;&gt;
&lt;h3 id=&#34;org8feef9b&#34;&gt;Markdown settings&lt;/h3&gt;
&lt;div class=&#34;outline-text-3&#34; id=&#34;text-org8feef9b&#34;&gt;
&lt;p&gt;
Add these customization to Emacs config:
&lt;/p&gt;</description>
    </item>
    <item>
      <title>TensorFlow Developer Certificate: My Tips</title>
      <link>/notes/20201005_tensorflow_developer_certificate_my_tips/</link>
      <pubDate>Mon, 05 Oct 2020 00:00:00 +0000</pubDate>
      <guid>/notes/20201005_tensorflow_developer_certificate_my_tips/</guid>
      <description>&lt;p&gt;
I recently got my &lt;a href=&#34;https://www.tensorflow.org/certificate&#34;&gt;TensorFlow Developer Certificate&lt;/a&gt;. Here are some tips I learned from my latest experience with the exam.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Preparation&lt;/b&gt;: Get familiar with Python coding and TensorFlow (of course!). Take some courses if needed. There are plenty of online courses available these days. For example, I found &lt;a href=&#34;https://www.coursera.org/professional-certificates/tensorflow-in-practice&#34;&gt;TensorFlow in Practice&lt;/a&gt; helpful to my preparation. Also, make sure you read the &lt;a href=&#34;https://www.tensorflow.org/extras/cert/TF_Certificate_Candidate_Handbook.pdf&#34;&gt;candidate handbook&lt;/a&gt; before taking the exam.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;PyCharm setup&lt;/b&gt;: You’ll take the exam in PyCharm. So it’ll be a good idea to play around a bit with this IDE. I recommend setting up a practice project according to the instructions in candidate handbook, so that you’ll have an idea what the environment will look like.
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Fix A Problem When Applying .tmux.conf</title>
      <link>/notes/20200610_fix_a_problem_when_applying_tmux_conf/</link>
      <pubDate>Wed, 10 Jun 2020 00:00:00 +0000</pubDate>
      <guid>/notes/20200610_fix_a_problem_when_applying_tmux_conf/</guid>
      <description>&lt;p&gt;
For some reason I’m starting to get this error when I apply tmux configuration:
&lt;/p&gt;

&lt;div class=&#34;org-src-container&#34;&gt;
&lt;pre class=&#34;src src-shell&#34;&gt;cut -c3- ~/.tmux.conf | sh -s _apply_configuration returned -2
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
So the problem is that “sh” used to work here, but at some point it doesn’t when a new shell is installed. Furthermore, I guess the reason is that “sh” used to be resolved into “bash” and the syntax was written in bash accordingly. If “sh” gets resolved into some other shell, it might cause syntax error or something.
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Fix a Problem in Emacs Python/Jupyter setup</title>
      <link>/notes/20200328_fix_a_problem_in_emacs_python_jupyter_setup/</link>
      <pubDate>Sat, 28 Mar 2020 00:00:00 +0000</pubDate>
      <guid>/notes/20200328_fix_a_problem_in_emacs_python_jupyter_setup/</guid>
      <description>&lt;p&gt;
I’ve configured my Emacs with a nice Python and Jupyter environment. I want to &lt;a href=&#34;../20190827_run_emacs_server_on_macos/&#34;&gt;use it on my Mac laptop&lt;/a&gt;. Recently I noticed this strange issue:
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;Problem&lt;/b&gt;: I send my code to Jupyter using C-c C-c, the Jupyter console shows a bunch of strange “Ctrl-G” (“&lt;sup&gt;G&lt;/sup&gt;”) characters. My code was not executed, and the console seems to be stuck there. I have to press Ctrl-C to get back to shell.
&lt;/p&gt;


&lt;div id=&#34;orgffb0079&#34; class=&#34;figure&#34;&gt;
&lt;p&gt;&lt;img src=&#34;../images/2020/03/image-1.png&#34; alt=&#34;image-1.png&#34; width=&#34;480px&#34; /&gt;
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Exporting .org files to HTML in batch</title>
      <link>/notes/20200109_exporting_org_files_to_html_in_batch/</link>
      <pubDate>Thu, 09 Jan 2020 00:00:00 +0000</pubDate>
      <guid>/notes/20200109_exporting_org_files_to_html_in_batch/</guid>
      <description>&lt;p&gt;
I use org-mode in Emacs and have multiple .org files to track different information in my life. Sometimes I want to export my .org files as HTML so they can be easily viewed on another device. The org-mode package does provide commands to do this on individual file (such as “org-html-export-to-html”), but doing this on each file manually is tedious. So I decided to write my own elisp function to augment my Emacs environment.
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Solving a magit issue with Emacs 26.3</title>
      <link>/notes/20191218_solving_a_magit_issue_with_emacs_26_3/</link>
      <pubDate>Wed, 18 Dec 2019 00:00:00 +0000</pubDate>
      <guid>/notes/20191218_solving_a_magit_issue_with_emacs_26_3/</guid>
      <description>&lt;p&gt;
Some point after my Emacs was upgraded to 26.3, I started seeing errors whenever I try to open file from git repository (i.e. directories with .git subdirectory). The error was annoying as it prevented me from opening files.
&lt;/p&gt;

&lt;p&gt;
So I dig a little into the error and found out that it was from magit (the package that deals with git stuff). The error was caused by wrong argument number provided to function magit-turn-on-auto-revert-mode-if-desired:
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Run Emacs Server on MacOS</title>
      <link>/notes/20190827_run_emacs_server_on_macos/</link>
      <pubDate>Tue, 27 Aug 2019 00:00:00 +0000</pubDate>
      <guid>/notes/20190827_run_emacs_server_on_macos/</guid>
      <description>&lt;p&gt;
Ok, I’ve been using Emacs for a long time and my Emacs config file is getting bigger and more complex. Emacs is a powerful tool, but it can take longer time to start up with a big config file. However, I want Emacs to be my go-to editor instead of just a heavy-weight IDE. I want to use Emacs when I want to quickly edit something (like “vim &amp;lt;something&amp;gt;” or “nano &amp;lt;something&amp;gt;”). How do I do that with Emacs?
&lt;/p&gt;</description>
    </item>
    <item>
      <title>How to Run GUI Application in Windows Subsystem for Linux (WSL)</title>
      <link>/notes/20190810_how_to_run_gui_application_in_windows_subsystem_for_linux/</link>
      <pubDate>Sat, 10 Aug 2019 00:00:00 +0000</pubDate>
      <guid>/notes/20190810_how_to_run_gui_application_in_windows_subsystem_for_linux/</guid>
      <description>&lt;div id=&#34;outline-container-orga03ddd0&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;orga03ddd0&#34;&gt;Install WSL&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-orga03ddd0&#34;&gt;
&lt;p&gt;
Basically you need to turn on WSL in Program Features. Refer to this document for the steps:
&lt;a href=&#34;https://docs.microsoft.com/en-us/windows/wsl/install-win10&#34;&gt;https://docs.microsoft.com/en-us/windows/wsl/install-win10&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org759c97e&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org759c97e&#34;&gt;Install Linux distribution in WSL&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org759c97e&#34;&gt;
&lt;p&gt;
Refer to same document for steps. I installed Ubuntu but there are other distributions available.
&lt;a href=&#34;https://docs.microsoft.com/en-us/windows/wsl/install-win10&#34;&gt;https://docs.microsoft.com/en-us/windows/wsl/install-win10&lt;/a&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id=&#34;outline-container-org0f536f9&#34; class=&#34;outline-2&#34;&gt;
&lt;h2 id=&#34;org0f536f9&#34;&gt;Install Dependencies&lt;/h2&gt;
&lt;div class=&#34;outline-text-2&#34; id=&#34;text-org0f536f9&#34;&gt;
&lt;p&gt;
GUI applications may have additional dependencies (libraries, etc). An easy way to install proper libraries is by installing some GUI programs, which will automatically resolve and install needed libraries. For example:
&lt;/p&gt;</description>
    </item>
    <item>
      <title>Easy Web Hosting on Alibaba Cloud – Simple Application Server &#43; HTTPS Setup</title>
      <link>/notes/20190729_easy_web_hosting_on_alibaba_cloud_simple_application_server_https_setup/</link>
      <pubDate>Mon, 29 Jul 2019 00:00:00 +0000</pubDate>
      <guid>/notes/20190729_easy_web_hosting_on_alibaba_cloud_simple_application_server_https_setup/</guid>
      <description>&lt;p&gt;
I’ve been thinking about creating a personal website for a while, and finally I put it into action!
&lt;/p&gt;

&lt;p&gt;
There are lots of ways to host a personal website on Alibaba Cloud, just like you will expect from other cloud providers. I picked Simple Application Server which is pretty much a lightweight virtual machine instance with pre-installed configurations (WordPress, Apache, etc). This gives me flexibility of a VM instance, but saves me from the initial setup. A good balance between their Web Hosting and Elastic Computing Service (ECS) in my opinion.
&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
