解决容器内运行conda的GLIBCXX问题

尝试在容器内运行conda,发现报错如下: conda "ImportError: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.26' not found" 解决方式 安装libgcc conda install libgcc 如果仍然报错,则 export LD_LIBRARY_PATH=<conda-env-path>/lib:$LD_LIBRARY_PATH conda-env-path替换为conda的目录,核心是通过修改LD_LIBRARY_PATH,让conda的python正确加载conda安装的libstdc++,而非系统的版本 To-Ask 为什么需要配环境变量? 按理来说conda在安装时应当已经修改了bashrc、zshrc等文件,让shell环境里的LD_LIBRARY_PATH带上了conda的lib目录(需要检查下未挂载home目录的容器以确认)。有可能是因为在启动容器时挂载了整个home目录,导致容器内的bash用了host的配置所致。 仔细想想,虽然挂载整个home目录用起来方便,但像shell配置、各类软件的cache本身是应该与host独立的,最好还是挂载home下的特定目录

2023-01-03 · Qiao

在容器内使用显卡进行渲染

由于要测试PyTorch3D生成的Mesh,而PyTorch3D的环境在本机又不好搭建,准备在Docker容器内做些渲染相关的工作,按关键词nvidia opengl docker搜索了一番,发现应该很好完成。 结合几篇文章的内容,以及nvidia/opengl的Dockerfile来看,核心是安装libglvnd0及一些依赖库、配置好glvnd的vendor json文件、设置nvidia docker的环境变量即可,但一番操作下来,在容器内安装mesa-utils和glmark2后,用glxinfo和glmark2都显示vendor是: OpenGL renderer string: llvmpipe (LLVM 11.0.0, 256 bits) 即仍然在使用软渲染,但nvidia-smi在容器内工作又是正常的。 使用集显 在Host机器上测试glxinfo和glmark2,发现vendor居然也不是nvidia而是MESA Intel,也就是电脑的集成显卡。不过集成显卡就集成显卡吧,好歹让容器能够用集显,这样工作好歹可以继续。 测试后,发现在docker run时附带--device=/dev/dri:/dev/dri参数即可。这样操作后,容器内glxinfo总算显示vendor是集成显卡了,由于工作要求的渲染性能不高,代码倒也能跑起来。 关于Linux DRI,可参考Linux graphic subsystem(2)_DRI介绍的说明 使用独显 话说回来,为什么host和容器都显示vendor是集显而非Nvidia的独显?明明nvidia-smi工作正常,CUDA的代码也能运行。带此疑问,用why glxinfo not detect nvidia while nividia-smi works搜索一番,发现Nvidia的论坛里也有些相似的问题,但求助都没有明确答复。 最后本机上打开nvidia-settings查看设置时,发现Profile里的3个选项: Nvidia (Performance mode) Nvidia On-Demand Intel (Power saving mode) 第3个很好理解,但Nvidia Performance mode和On-Demand又有什么区别?搜索一番,发现此贴: Nvidia On - Demand : Ubuntu there’s a good write up here: https://www.linuxuprising.com/2019/08/nvidia-43517-linux-beta-driver-adds.html on-demand means the Ubuntu optimus tool now lets you have dynamic switching of nvidia, but output is limited to the laptop screen, which is ‘bumblebee mode’, or the normal ubuntu Nvidia mode, which turns on the card after you restart X; this mode uses nvidia to render everything, and external monitors work. But you can’t turn the card off without ending your X session. ...

2023-01-01 · Qiao

Use docker with Nvidia GPU in WSL2

GPU Support 先确认Docker Desktop的Backend使用的是WSL2,并且Windows、Nvidia驱动的版本足够,随后管理员权限终端执行wsl --update更新wsl。完成后,终端执行 docker run --rm -it --gpus=all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark 如果GPU可用,则输出类似于 Run "nbody -benchmark [-numbodies=<numBodies>]" to measure performance. -fullscreen (run n-body simulation in fullscreen mode) -fp64 (use double precision floating point values for simulation) -hostmem (stores simulation data in host memory) -benchmark (run benchmark to measure performance) -numbodies=<N> (number of bodies (>= 1) to run in simulation) -device=<d> (where d=0,1,2.... for the CUDA device to use) -numdevices=<i> (where i=(number of CUDA devices > 0) to use for simulation) -compare (compares simulation results running once on the default GPU and once on the CPU) -cpu (run n-body simulation on the CPU) -tipsy=<file.bin> (load a tipsy model file for simulation) > NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled. > Windowed mode > Simulation data stored in video memory > Single precision floating point simulation > 1 Devices used for simulation MapSMtoCores for SM 7.5 is undefined. Default to use 64 Cores/SM GPU Device 0: "GeForce RTX 2060 with Max-Q Design" with compute capability 7.5 > Compute 7.5 CUDA device: [GeForce RTX 2060 with Max-Q Design] 30720 bodies, total time for 10 iterations: 69.280 ms = 136.219 billion interactions per second = 2724.379 single-precision GFLOP/s at 20 flops per interaction Use docker in WSL Docker Desktop的settings-resources-WSL Integration勾选"Enable intergration with my default WSL distro"以及所需的发行版,点击"Refresh",随用Windows Terminal新打开WSL发行版的终端即可。输入 docker --version > Docker version 20.10.21, build baeda1f 有版本号说明docker集成正常 Use docker with GPU in WSL 完成以上步骤后,在WSL里同样可以用docker run --gpus=all的方式在WSL的docker里启用GPU,例如: ...

2022-12-13 · Qiao

使用Github Actions部署Hexo

切换到Hexo写博客后,每次换电脑都要来遍NodeJS、Hexo的配置。虽然不算困难,但挺消耗写文章的心情,故决定折腾下Github CI,实现写完文章后推送就自动完成Hexo的生成和部署,这样方便专注于文章的撰写,不被环境搭建分散精力。 设置仓库 准备两个仓库,一个为博客源码仓库,一个是静态页面仓库。 博客源码仓库:名称任意,设为私有 静态页面仓库:名称需按照xxx.github.io格式来,必须设为公开的,存放Hexo生成的内容。参考https://pages.github.com/ 设置密钥 为了向静态页面仓库推送内容,需要添加一对SSH密钥,其中公钥设置到静态页面仓库,私钥设置到源码仓库。 生成密钥 ssh-keygen -t ed25519 -C "your_email@example.com" 在Github的静态仓库页面,添加新的Deploy Key。在Settings -> Deploy keys -> Add new中,填入任意Title,Value则是新生成的公钥内容。由于要往此仓库推送,需勾选”Allow Write Access“。 在Github的源码仓库页面,在Settings -> Secrets -> Actions中点击New repository secret,Name设置为DEPLOY_KEY(后面配置Github Actions的脚本时会用NAME索引到此secret),Value填入新生成私钥的内容 定义Workflows 在源码仓库根目录下,创建.github/workflows/hexo_deploy.yml文件,内容如下: name: HEXO_DEPLOY on: push: branches: - master jobs: build: runs-on: ubuntu-latest steps: - name: Checkout source uses: actions/checkout@v2.5.0 with: ref: master submodules: 'true' - name: Use Node.js uses: actions/setup-node@v3 with: node-version: 18 - name: Setup hexo env: ACTION_DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} run: | mkdir -p ~/.ssh/ echo "$ACTION_DEPLOY_KEY" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan github.com >> ~/.ssh/known_hosts git config --global user.email "qiaotanmail@gmail.com" git config --global user.name "tanqiao" npm install hexo-cli -g npm install - name: Hexo deploy run: | hexo clean hexo deploy 修改源码仓库根目录Hexo的_config.yml文件,设置deploy方式: ...

2022-12-10 · Qiao

利用strace查找文件热点

在做性能调优时,遇到这么一个问题:已知国产机(飞腾+麒麟OS)上机械硬盘的性能非常差,文件读写会有不少开销,那么怎么跟踪程序的读写情况,尽量优化掉不必要的读写呢?这需要查找文件热点。对于这项工作,BPF Compiler Collection里的filetop是个很好的选择,不过BCC这组工具在麒麟OS源里没有提供,遂考虑用strace实现。 跟踪系统调用 严格来说,strace并不能直接跟踪文件的读写情况,而是跟踪所有接受一个文件名为参数的系统调用。不过无论是频繁读写还是频繁判断文件状态,对于调优而言都是可待优化的,因此这里没有严格区分两者。 跟踪文件相关的系统调用: $ strace -t -e trace=file -o strace.log COMMAND # --trace=file # Trace all system calls which take a file name as an argument. You can think of this as an abbreviation for -e trace=open,stat,chmod,unlink,... which is useful to seeing what files the process is referencing. --trace=还可以使用process、network、signal、desc、memory等等,参见https://man7.org/linux/man-pages/man1/strace.1.html 示例 $ strace -t -e trace=file -o strace.log fc-list $ cat strace.log 18:07:24 execve("/home/tanqiao/program/hotspot/hotspot", ["hotspot"], 0x7ffc0b28a138 /* 80 vars */) = 0 18:07:24 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (没有那个文件或目录) 18:07:24 openat(AT_FDCWD, "/usr/local/cuda-11.5/lib64/tls/x86_64/x86_64/libtinfo.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录) 18:07:24 stat("/usr/local/cuda-11.5/lib64/tls/x86_64/x86_64", 0x7ffc75b3d900) = -1 ENOENT (没有那个文件或目录) 18:07:24 openat(AT_FDCWD, "/usr/local/cuda-11.5/lib64/tls/x86_64/libtinfo.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录) 18:07:24 stat("/usr/local/cuda-11.5/lib64/tls/x86_64", 0x7ffc75b3d900) = -1 ENOENT (没有那个文件或目录) 18:07:24 openat(AT_FDCWD, "/usr/local/cuda-11.5/lib64/tls/x86_64/libtinfo.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录) 18:07:24 stat("/usr/local/cuda-11.5/lib64/tls/x86_64", 0x7ffc75b3d900) = -1 ENOENT (没有那个文件或目录) 18:07:24 openat(AT_FDCWD, "/usr/local/cuda-11.5/lib64/tls/libtinfo.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录) 18:07:24 stat("/usr/local/cuda-11.5/lib64/tls", 0x7ffc75b3d900) = -1 ENOENT (没有那个文件或目录) 18:07:24 openat(AT_FDCWD, "/usr/local/cuda-11.5/lib64/x86_64/x86_64/libtinfo.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录) 18:07:24 stat("/usr/local/cuda-11.5/lib64/x86_64/x86_64", 0x7ffc75b3d900) = -1 ENOENT (没有那个文件或目录) 文件处理 用grep去除打开失败的文件 $ cat strace.log | grep -v 'ENOENT' # -v, --invert-match 改变匹配的意义,只选择不匹配的行 用awk提取双引号内的值 $ awk -F '"' '{print $2}' 结合sort和uniq去重 $ sort | uniq -c # uniq # -c, --count 每行前附上重复出现的次数作为前缀 输出类似于: ...

2022-02-25 · Qiao

Add dynamic tracing point in C++ dynamic library

List functions To list all functions exported $ perf probe -x libQt5CoreKso.so --funcs --filter '*' If you don’t add --filter '*', then all functions that start with _ will be filtered by default To list all functions in original form: $ perf probe -x libQt5CoreKso.so --funcs --no-demangle --filter '*' Combine with grep, you can find the desired function $ perf probe -x libQt5CoreKso.so --funcs --no-demangle --filter '*' | grep setValue _ZN6kso_qt11QJsonObject10setValueAtEiRKNS_10QJsonValueE _ZN6kso_qt18QCommandLineOption12setValueNameERKNS_7QStringE _ZN6kso_qt24QVariantAnimationPrivate10setValueAtEdRKNS_8QVariantE _ZN6kso_qt9QSettings8setValueERKNS_7QStringERKNS_8QVariantE Add tracing point To add a function as tracing point: ...

2022-02-25 · Qiao

用Rclone在Linux下与OneDrive同步

接触Obsidian以后,决心将笔记从OneNote转换成Markdown格式,再由Obisian管理,同步则还是用OneDrive。OneDrive在Linux下没有客户端,不过可以借助Rclone与OneDrive API交互做同步。 安装 curl https://rclone.org/install.sh | sudo bash 配置 Rclone的文档相当齐全,这里参考https://rclone.org/onedrive/ 进行配置。终端输入 rclone config 按提示设定storage的名称(这里设定为onedrive),选择storage类型为Microsoft OneDrive,随后Rclone会唤起浏览器打开登录页面 e) Edit existing remote n) New remote d) Delete remote r) Rename remote c) Copy remote s) Set configuration password q) Quit config e/n/d/r/c/s/q> n name> onedrive Type of storage to configure. Enter a string value. Press Enter for the default (""). Choose a number from below, or type in your own value [snip] XX / Microsoft OneDrive \ "onedrive" [snip] Storage> onedrive Microsoft App Client Id Leave blank normally. Enter a string value. Press Enter for the default (""). client_id> Microsoft App Client Secret Leave blank normally. Enter a string value. Press Enter for the default (""). client_secret> Edit advanced config? (y/n) y) Yes n) No y/n> n Remote config Use auto config? * Say Y if not sure * Say N if you are working on a remote or headless machine y) Yes n) No y/n> y If your browser doesn't open automatically go to the following link: http://127.0.0.1:53682/auth Log in and authorize rclone for access Waiting for code... Got code Choose a number from below, or type in an existing value 1 / OneDrive Personal or Business \ "onedrive" 2 / Sharepoint site \ "sharepoint" 3 / Type in driveID \ "driveid" 4 / Type in SiteID \ "siteid" 5 / Search a Sharepoint site \ "search" Your choice> 1 Found 1 drives, please select the one you want to use: 0: OneDrive (business) id=b!Eqwertyuiopasdfghjklzxcvbnm-7mnbvcxzlkjhgfdsapoiuytrewqk Chose drive to use:> 0 Found drive 'root' of type 'business', URL: https://org-my.sharepoint.com/personal/you/Documents Is that okay? y) Yes n) No y/n> y -------------------- [remote] type = onedrive token = {"access_token":"youraccesstoken","token_type":"Bearer","refresh_token":"yourrefreshtoken","expiry":"2018-08-26T22:39:52.486512262+08:00"} drive_id = b!Eqwertyuiopasdfghjklzxcvbnm-7mnbvcxzlkjhgfdsapoiuytrewqk drive_type = business -------------------- y) Yes this is OK e) Edit this remote d) Delete this remote y/e/d> y 使用 复制 从本地复制到OneDrive: ...

2022-02-25 · Qiao

poor-man-s-profiler

背景 Linux下perf可以说是首选的性能调优工具——无需重新编译目标软件,支持采样多种类型的事件,开销相对较小。不过perf也有明显的缺点,perf是通过采样事件(并且通常都是采样CPU事件)来记录软件运行情况的,因此它的结果往往只能反映程序在某一方面的表现。 换而言之,如果perf采样的是CPU事件,那么其结果只能代表程序On-CPU的表现,至于Off-CPU部分则需要另外采样。虽然也可以通过采样sched:sched_stat_sleep、sched:sched_switch、sched:sched_process_exit来间接分析Off-CPU的情况,但Off-CPU瓶颈的类型可能有很多(IO、线程同步、内存等),只采样特定事件分析容易有所遗漏。 这自然地引出一个问题:有没有工具能够按固定时间间隔记录程序当前调用栈? 不幸的是,perf虽然支持记录cpu-clock、task-clock事件,但内核并没有提供类似于wall-clock的事件。其它采样工具,诸如gprof、gperftools、Valgrind也是如此。 poor man’s profiler 所谓的poor man’s profiler,其原理非常简单。用GDB启动(或关联到)进程,并按一定间隔中断进程并检查当前调用栈,函数的开销则与其在调用栈中出现的频率成正比。 一个简单的实现,poor-profiler.sh: #!/bin/bash set -e command="" sample_number=100 sleep_time=0.01 output_file="poorman-profiler.log" PID=0 # parse arguments while getopts e:n:t:o:p: flag do case "${flag}" in e) command=${OPTARG} ;; n) sample_number=${OPTARG} ;; t) sleep_time=${OPTARG} ;; o) output_file=${OPTARG} ;; p) PID=${OPTARG} ;; *) echo "${OPTARG} are ignored" >&2 ;; esac done # remove old log if [ -f "$output_file" ] ; then rm -v "$output_file" fi # run command in background if not empty if [ -n "$VAR" ]; then ${command} & PID=$! fi # attach gdb periodically for x in $(seq 1 "$sample_number"); do sleep "$sleep_time" # check if process is running if kill -s 0 $PID ; then gdb -ex "set pagination 0" -ex "thread apply all bt" -batch -p $PID 2>/dev/null | tee -a "$output_file" else break fi done 使用方式: ...

2022-02-11 · Qiao

处理托管C++的EEFileLoadException

背景 因为业务的原因,需要从C++端调用一个C#库,设计的调用流程如下: graph LR; n["Native C++"]-->m["Managed C++"]; m-->s["C#"]; 工程的组织如下: graph LR; subgraph "Native C++" user["Native C++库使用者"] nt["Native C++库单元测试"]; n["Native C++库"]; end m["Managed C++库"]; subgraph "C#" s["C#库"]; st["C#库单元测试"]; end user-.->|显式加载|n; nt-->n; n-->m; m-->s; st-->s; 动态库工程: Native C++库:生成Unmanaged.lib和Unmanaged.dll Managed C++库:生成Wrapper.lib和Wrapper.dll C#库:生成Managed.dll 可执行文件工程: Native C++库单元测试:生成UnmanagedTest.exe C#库单元测试:生成ManagedTest.exe Native C++库使用者:生成LibConsumer.exe。与单元测试工程不同的是,LibConsumer.exe会在运行期间调用::LoadLibrary()显示加载Unmanaged.dll,在链接期也不会链接到Unmanaged.lib和Wrapper.lib 现在情况如下:C#库编写完成,且C#库单元测试通过,但Native C++库单元测试未通过,LibConsumer.exe加载Unmanaged.dll也会失败(::LoadLibrary()返回句柄为NULL)。调试发现在托管C++层创建C#对象时会出现EEFileLoadException导致程序崩溃。 EEFileLoadException Microsoft Docs没有找到对EEFileLoadException的描述,不过Stackoverflow上有个简要的回答,见EEFileLoadException When Loading C++ DLL in Managed DLL: An EEFileLoadException indicates the executable cannot find or load one of it’s dependencies. That can of course has different causes (path problem, mixing configurations, mixing platforms). ...

2020-11-04 · Qiao

在Windows环境下编译Qt-5-15-1

自Qt 5.15开始,Qt对于开源用户只提供源码包的下载,不再提供预编译安装包。这一策略或是为了促使更多人购买Qt的商用授权。无论对这一决策的态度如何,自Qt 5.15开始,无论是使用静态库还是动态库,编译Qt都将是一个必不可少的步骤了。 1 源码下载 Qt 5.15.1的下载地址:Qt 5.15.x source packages 也可以从国内的镜像下载,Qt的镜像列表:https://download.qt.io/static/mirrorlist/ 下载qt-everywhere-src-5.15.1.zip后解压,这里假定将源码解压到qt5.15.1-src目录。 2 编译环境搭建 在Windows环境下从源码编译安装Qt,除VS开发环境外,还需要先安装Perl和Python。此外,还有一些可选的三方库可以安装,如OpenSSL Toolkit、ICU、ANGLE,这些库可以为Qt提供额外的特性,但并不是必要的,参见Qt官方文档对编译环境的描述:Qt for Windows - Requirements Qt 5.14。 2.1 Visual Studio Qt可以使用VS 2015,VS 2017,VS 2019进行构建。这里选择使用VS 2019,从https://visualstudio.microsoft.com/zh-hans/ 下载安装即可。 2.2 Perl Perl的Windows版本有2种可以下载,分别是ActivePerl和StrawberryPerl。其中ActivePerl需要注册后下载,StrawberryPerl可以直接下载,推荐StrawberryPerl。 StrawberryPerl下载地址:Strawberry Perl for Windows 安装时默认会添加perl到环境变量。安装完成后,可以通过命令行执行perl -v测试环境变量是否安装成功。 2.3 Python 对于Python,Python 2只被qpdf、qwebengine等几个模块需要,如果不需要这几个模块可以只安装Python 3。这里选择只安装Python 3。 在Windows 10下安装Python的注意事项 从Windows 10 2019 五月更新以来,微软试图把 Python 带到 Windows,因此在C:\Users\%USERNAME%\AppData\Local\Microsoft\WindowsApps路径下加入了python.exe、python3.exe几个占位文件。 这几个文件并非真正的python解释器,执行后会弹出Windows Store页面并定位到Python App的详情页。由于这几个文件也处在系统的PATH环境变量内,当用户执行python时有可能会调用占位文件而非实际的python解释器,从而导致运行错误。 可以通过以下步骤关闭该设置: 输入app exec打开Windows的“应用程序别名”界面 关闭为python.exe和python2.exe设置的别名 下载Python:Python Releases for Windows Python.org 安装时选择将Python加入环境变量。可以在命令行内输入python,检查Python解释器是否会运行。 ...

2020-09-21 · Qiao