周刊项目地址 https://github.com/wanghenshui/cppweeklynews
RSS https://github.com/wanghenshui/cppweeklynews/releases.atom
欢迎投稿,推荐或自荐文章/软件/资源等
请提交 issue https://github.com/wanghenshui/cppweeklynews/issues
最近在找工作准备面试题,更新可能有些拖沓,见谅
本期文章由 黄亮Anthony HNY 赞助
资讯
标准委员会动态/ide/编译器信息放在这里
clion新增AI助手 https://www.jetbrains.com/clion/whatsnew/
编译器信息最新动态推荐关注hellogcc公众号 OSDT Weekly 2023-12-06 第231期
文章
- • 现代C 语言核心特性解析C 23标准补充 - 免费电子书 https://zhuanlan.zhihu.com/p/670502105
感兴趣的可以看一下。很短
- • Outline: 代码分离编译优化 https://zhuanlan.zhihu.com/p/669417318
抽出相同的二进制,节省二进制大小。和inline逻辑相反
可能会有性能衰退
原理?如何找出重复的二进制序列?后缀树爆搜
也可以从不同角度来做,比如IR层
具体很细节。感兴趣的可以看看
- • HotColdSplitting: 代码分离之性能优化 https://zhuanlan.zhihu.com/p/670400568
借助outline做冷热分离,有性能提升,还挺有意思的,算是PGO一部分吧,拿到profile来分析
- • For processing strings, streams in C can be slow https://lemire.me/blog/2023/10/19/for-processing-strings-streams-in-c-can-be-slow/
stream就是垃圾 strstream没人用。感觉后面会演进个spanstream出来
- • Parsing 8-bit integers quickly https://lemire.me/blog/2023/11/28/parsing-8-bit-integers-quickly/
lamire博士新活
常规
代码语言:javascript复制int parse_uint8_naive(const char *str, size_t len, uint8_t *num) {
uint32_t n = 0;
for (size_t i = 0, r = len & 0x3; i < r; i ) {
uint8_t d = (uint8_t)(str[i] - '0');
if (d > 9)
return 0;
n = n * 10 d;
}
*num = (uint8_t)n;
return n < 256 && len && len < 4;
}
当然c 可以用from chars加速
代码语言:javascript复制int parse_uint8_fromchars(const char *str, size_t len, uint8_t *num) {
auto [p, ec] = std::from_chars(str, str len, *num);
return (ec == std::errc());
}
能不能更快?这是u8场景,考虑SWAR,组成一个int来处理
代码语言:javascript复制int parse_uint8_fastswar(const char *str, size_t len,
uint8_t *num) {
if(len == 0 || len > 3) { return 0; }
union { uint8_t as_str[4]; uint32_t as_int; } digits;
memcpy(&digits.as_int, str, sizeof(digits));
digits.as_int ^= 0x30303030lu;
digits.as_int <<= ((4 - len) * 8);
uint32_t all_digits =
((digits.as_int | (0x06060606 digits.as_int)) & 0xF0F0F0F0)
== 0;
*num = (uint8_t)((0x640a01 * digits.as_int) >> 24);
return all_digits
& ((__builtin_bswap32(digits.as_int) <= 0x020505));
}
评论区bob给了个更快的
代码语言:javascript复制int parse_uint8_fastswar_bob(const char *str, size_t len, uint8_t *num) {
union { uint8_t as_str[4]; uint32_t as_int; } digits;
memcpy(&digits.as_int, str, sizeof(digits));
digits.as_int ^= 0x303030lu;
digits.as_int <<= (len ^ 3) * 8;
*num = (uint8_t)((0x640a01 * digits.as_int) >> 16);
return ((((digits.as_int 0x767676) | digits.as_int) & 0x808080) == 0)
&& ((len ^ 3) < 3)
&& __builtin_bswap32(digits.as_int) <= 0x020505ff;
}
压测代码在这里 https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/tree/master/2023/11/28 感兴趣可以玩一玩
- • Nerd Snipe: Small Integer Parsing https://blog.loadzero.com/blog/parse-int-nerdsnipe/
场景 完美hash,4bytes字符串做key,如何快速算hash?
直接把字符串当成int来算
代码语言:javascript复制#define SIZE 512
uint8_t lut[SIZE] = {};
// multiply, shift, mask
uint32_t simple_hash(uint32_t u) {
uint64_t h = (uint64_t) u * 0x43ff9fb13510940a;
h = (h >> 32) % SIZE;
return (uint32_t) h;
}
// generate, cast and hash
void build_lut() {
char strings[256*4];
memset(strings, 0, sizeof(strings));
char *iter = strings;
for (int i = 0; i < 256; i) {
sprintf(iter, "%d", i);
iter = 4;
}
iter = strings;
for (int i = 0; i < 256; i) {
unsigned c = *(unsigned*) iter;
iter = 4;
unsigned idx = simple_hash(c);
lut[idx] = i;
}
}
视频
cppcon2023 工作日开始更新视频了,这周好玩的列一下
- • A Long Journey of Changing std::sort Implementation at Scale - Danila Kutenin - CppCon 2023 https://www.youtube.com/watch?v=cMRyQkrjEeI
这个作者danlark在llvm比较活跃
这个视频非常值得一看,列举了sort的改进优化,各个系统的差异,以及nth_element的副作用问题
很多库写的median算法实际是错的!
https://godbolt.org/z/9xWoYTfMP
代码语言:javascript复制
int median(std::vector<int>& v) {
int mid = v.size() / 2;
std::nth_element(v.begin(), v.begin() mid, v.end());
int result = v[mid];
if (v.size() % 2 == 0) {
std::nth_element(v.begin(), v.begin() mid - 1, v.end());
result = (v[mid] v[mid-1])/2;
// result = (result v[mid-1]) /2;
}
return result;
}
由于nth_element不保证整体有序,只保证n的位置是对的,所以第二次的计算可能改变第一次的结果
然而社区很多median实现都是错的
- • Customization Methods: Connecting User and C Library Code - Inbal Levi - CppCon 2023 https://www.youtube.com/watch?v=mdh9GLWXWyY
介绍了一些查找逻辑的设计,从swap到ADL,到CPO tag_invoke 再到最近的讨论,有Custom function设计
还算有意思 。但有句讲句tag_invoke很扭曲,cpo也是
- • Variable Monitoring with Declarative Interfaces - Nikolaj Fogh - Meeting C 2023 https://www.youtube.com/watch?v=AJDbu1kaj5g
介绍一个库 https://github.com/nfogh/monitoring/
代码语言:javascript复制auto myMonitor = Monitor([](int i){ return i > 0; }, [](bool valid){ std::cout << "Valid: " << valid << std::endl; }]);
int variable = 0;
myMonitor(variable); // Prints Valid: 0
variable = 1;
myMonitor(variable); // Prints Valid: 1
不过不知道有啥用途。signal handler类似的玩意
比如监控内存,真到了瓶颈,直接在发现的位置条件判断也不是不行
或者类似bvar之类的玩意,把数据导出 回调交给别的组件
不知道什么场景能用上
有意思的项目
- • https://github.com/sunxfancy/vscode-llvm 在vscode里拿到llvm compiler explore类似的效果。检查IR,查看CFG之类的,很厉害
- • asteria https://github.com/lhmouse/asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群753302367和作者对线 (原来的群被举报了)
- • Unilang https://github.com/linuxdeepin/unilang deepin的一个通用编程语言,点子有点意思,也缺人,感兴趣的可以github讨论区或者deepin论坛看一看。这里也挂着长期推荐了
- • https://gitee.com/okstar-org/ok-edu-desktop 一个IM通信软件,做IM的可以关注,现在正在做全面整合阶段,开始组建商业团队阶段,年底开始融资,你参加了就快发财了,会的快来
互动环节
公众号终于收到了广告,不容易,预计19号发,挂一周。提前预告一下,大家别生气
最近面了好多工作,真有点迷茫了自己未来要做什么,年前就休息吧。随便看看了
引用链接
[1]
vwei@nvidia.com: mailto:vwei@nvidia.com