忘れてください

日常开发与实验

6 min read

日常开发#

由于我在两台设备上进行开发,虽然都是 wsl 环境(写 C/C++ 的暂时不考虑 Windows),所以多端的同步比较重要。

首先,确保 WSL 的版本与发行版一致,我选择的都是 WSL2 和 Ubuntu-24.04

我使用 github 来进行同步,步骤如下:

  1. 新建一个私有仓库
  2. 把 remote 的地址链接到两个电脑上
  3. 写完一个小版本后开始同步

注意,最好的方式是写完一个版本开始同步,但我们经常会存在功能一天写不完,晚上下班回去之后可能还会写一写的需求,我的做法是:

  1. 新建一个分支
  2. 提交暂存,然后同步
  3. 在这个分支上写完一整个功能后,向主分支提 pr,然后把 commit 历史 squash 再进行合并

这样就能保证主分支确实是一个功能一次 commit,保证 commit 清爽

实验#

由于组内服务器的使用不是每个人一个账号,并且也没有使用容器,总体来说比较随意(这样可能也会出现一些装环境的时候把服务器跑崩的问题,但鉴于组内没有做 system 的,其实这个风险也没有太大)

我的做法一般是,从 github 上 clone 我的代码 ,运行自己编写的 Dockerfile 和 docker-compose.yml,这样方便管理,因为一个文件夹就是一个容器(或者好几个容器,取决于实验的设计)

怎么跑实验#

一次可能需要跑好多 benchmark ,一个 benchmark 可能需要跑好几遍取平均,所以基本上是多进程跑,可以写一个 bash 脚本来做到这一点,例如:

./main -f data/instance/xxxx1.in -o eval/instance/1/xxxx1.out
./main -f data/instance/xxxx2.in -o eval/instance/1/xxxx2.out
./main -f data/instance/xxxx3.in -o eval/instance/1/xxxx3.out
./main -f data/instance/xxxx4.in -o eval/instance/1/xxxx4.out
./main -f data/instance/xxxx5.in -o eval/instance/1/xxxx5.out
./main -f data/instance/xxxx6.in -o eval/instance/1/xxxx6.out

可以通过命令:cat run.sh | xargs -P60 -d'\n' -n1 bash -c 来并行执行

xargs -P60 -d'\n' -n1 bash -c

  • xargs  是一个命令,用于从标准输入读取数据,并将其作为参数传递给另一个命令

  • -P60  选项:xargs  会并行地运行最多 60 个进程。这意味着  xargs  会同时启动 60 个  bash -c  进程来处理输入

  • -d'\n'  选项:指定输入的分隔符为换行符  \n。这意味着  xargs  会将输入的每一行作为一个单独的参数

  • -n1  选项:指定每次传递给  bash -c  的参数数量为 1。这意味着  xargs  会将每一行作为一个单独的命令传递给  bash -c

  • bash -c:bash -c  是一个命令,用于在新的 shell 中执行指定的命令。-c  选项后面跟着的是要执行的命令字符串

    但是,如何产生这个 run.sh 又成为一大问题

生成实验脚本#

这里我介绍一种很简单的方法:Python

我们可以让 LLM 写一个简单的 Python 脚本,遍历实例文件夹,来生成 run.sh ,例如一个 generate_run_cmd.py 简单如下:

import glob
import os

l = glob.glob("data/**/*.graph", recursive=True)

cmd = "./bin/Release/net8.0/fss {} > {}"

output_dir = "solution/"
os.makedirs(output_dir, exist_ok=True)

cmds = []
for f in l:
    output_dir = "solution/"
    if f.endswith(".graph"):
        output_dir += f.split("/")[-2]
        os.makedirs(output_dir, exist_ok=True)
        output_file = output_dir + '/' + os.path.basename(f).replace(".graph", ".sol")
        cmds.append(cmd.format(f, output_file))

with open("scripts/run.sh", "w+") as f:
    for c in cmds:
        f.write(c + "\n")

然后,我们可以再写一个 start 的脚本如下:

#!/bin/bash
python3 scripts/generate_run_cmd.py
cat run.sh | xargs -P60 -d'\n' -n1 bash -c

这样就可以一行命令 bash start 跑完一次实验了

(懒人版)生成实验脚本#

怎么统计数据#

这部分当然没有其他的路子,最简单的方法就是 LLM + Python,例如一个简单的 stats.py 如下所示:

import glob
import re

solution_lists = glob.glob('solution/*/**.sol', recursive=True)

pattern = r'\[solution\]\s+(\d+)\s+\[time\]\s+(\d+\.\d+)\s+us'

result = []


for file in solution_lists:
    with open(file, 'r') as f:
        content = f.readline().strip()
        match = re.search(pattern, content)
        if match:
            solution_size = match.group(1)
            time = match.group(2)
            result.append(
                {
                    "instance": file.split('/')[-1].split('.')[0],
                    "solution_size": solution_size,
                    "time(us)": time
                }
            )
        else:
            result.append(
                {
                    "instance": file.split('/')[-1].split('.')[0],
                    "solution_size": "N/A",
                    "time(us)": "TLE"
                }
            )

import pandas


df = pandas.DataFrame(result)
df.to_csv('solution_results.csv', index=False)

当然,你必须要做的事情就是:格式化输出

例如上面的例子中,我的输出被格式化为

[solution] 1035 [time] 8031755250.422 us

总之,Python 很好用,尤其在这种小事情上,Python + LLM 可以省下很多统计数据的时间,甚至还可以 直接画图

怎么知道实验结束(懒人版)#

参考文章 实验结束自动发送邮件 来进行设置

CONVERSATION

讨论

想法、补充,或只是打个招呼。

关系图谱 ↓

全局关系图谱

页面标签
笔记
↑ ↓ 选择↵ 打开Esc 关闭