V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tool2d
V2EX  ›  C++

在字符串性能上,传统 C++库被游戏业打的鼻青脸肿。

  •  
  •   tool2d · 87 天前 · 10952 次点击
    这是一个创建于 87 天前的主题,其中的信息可能已经有所发展或是发生改变。
    今年 2022 C++开发者大会上,有一个写游戏的作者,写了个基于 SIMD 优化的字符串,然后对比了传统 std::string 性能,几乎是秒杀了。

    要知道 std::string 也进化了那么多年,时至今日,还是被游戏业打的找不到北,只能说游戏业对于性能的无止尽追求的欲望,实在太强了。

    作者也开源了( www.youtube.co.jp/watch?v=fglXeSWGVDc ),并附上了性能对比截图:

    69 条回复    2023-01-10 16:53:57 +08:00
    julyclyde
        1
    julyclyde  
       87 天前
    std::string 只是个接口吧,又没规定具体怎么实现
    tool2d
        2
    tool2d  
    OP
       87 天前
    @julyclyde stl 标准库,怎么可能是接口呢。

    你去问任何一个写 C++的,都不推荐你自己改写 stl 的库,因为大概率没官方写的好。

    比如 std::string 这种,都是世界顶级科学家写出来的。
    julyclyde
        3
    julyclyde  
       87 天前   ❤️ 4
    @tool2d 你好像分不清标准库和标准模板库啊……
    建议你还是找任何一个写 C++的多问问,到底是接口还是实现
    yehoshua
        4
    yehoshua  
       87 天前 via Android   ❤️ 1
    std::string 毕竟只是标准库,具体应用场景要自己优化的。这是在游戏场景有大规模文字处理下的实现,不至于说传统库就不行了吧。
    cubecube
        5
    cubecube  
       87 天前
    如果没有 SIMD 呢?
    标准库要兼容各种运行场景不是
    tool2d
        6
    tool2d  
    OP
       87 天前
    @julyclyde 我知道你的意思,你不就是想说,不同的编译器,有自己特殊的 stl 库实现嘛。

    你看我那个截图,跨了 windows 平台,mac 平台, linux 平台。并且对比了 x64 和 arm 架构。

    stl 库的设计理念基本都是确定的,性能差距并没你想的那么大。
    jmc891205
        7
    jmc891205  
       87 天前
    std::string 的性能拉胯是众人皆知的
    julyclyde
        8
    julyclyde  
       87 天前
    @tool2d 不同编译器,各有各的实现方法,虽然也包含你说的 stl ,但其实在这个案例中并不是 stl 而是指标准库
    这事跟 stl 就没什么关系吧
    tool2d
        9
    tool2d  
    OP
       87 天前
    @cubecube "如果没有 SIMD 呢?"

    游戏业比较特殊,如果没有 SIMD ,游戏 FPS 就会直接减半,这点很多开发者都没办法接受。

    只能强制用户升级 CPU ,加上 AVX 之类的必要属性。
    pocarisweat
        10
    pocarisweat  
       87 天前   ❤️ 5
    std::string 首先就应该改名,这玩意只能叫做 std::bytes ,看看人 Rust 和 Swift 这些新语言是怎么处理不定长字符的。

    挑战 std::string 的实现非常多,因为字符串在太多领域实在是过于重要了。比如元宇宙公司的 FbString: https://github.com/facebook/folly/blob/main/folly/docs/FBString.md

    领域不同,导致对字符串性能的主要需求场景也不同,有些是字符串拼接,有些是快速复制,有些是查找,很难说某个实现真的全部适用。
    tool2d
        11
    tool2d  
    OP
       87 天前
    @julyclyde 我被你说的有一点晕,你看 std::string 的实现,是模板实现的啊。
    missdeer
        12
    missdeer  
       87 天前   ❤️ 16
    OP 的标题作为论点太狭隘了,应该说“在性能上,不用多媒体指令集的 C++库被用多媒体指令集的库打得鼻青脸肿”
    paoqi2048
        13
    paoqi2048  
       87 天前
    和 UnrealString 相比较呢?
    LaTero
        14
    LaTero  
       87 天前 via Android   ❤️ 9
    “一个写游戏的作者”,说得好像是一个人自己放假没事随便搞的一样,这明明是英伟达一堆雇员画了很长时间专门为图形领域优化的(主要体现在:字符串短,很多时候是从字符串字面量初始化来的,最常用的操作是连接两个字符串)。长字符串这个库和 libstdc++是持平的,而且因为比较 hacky (识别字符串字面量的方法)不可能放进标准库。
    Xusually
        15
    Xusually  
       87 天前
    这个 benchmark 图是 32 Byte String 的成绩,std::string 对长字符串的优化本身就稀烂,超短字符串性能还过得去。
    litmxs
        16
    litmxs  
       87 天前 via Android
    C++标准库里面的东西本来就拉跨,比如 regex
    没性能需求凑合用,有性能需求只能找找专门的第三方库或者自己手搓
    像 stl 这种,大部分第三方库或者框架都会自己实现一套,比如 Qt 、UE 、Google 的 Abseil ,Facebook 的 folly 等等
    andyhuzhill
        17
    andyhuzhill  
       87 天前
    std::string 性能一直不怎么样啊
    大多数的 C++工程都会实现自己的 string 类 不用 stl 的
    icyalala
        18
    icyalala  
       87 天前   ❤️ 31
    CppCon 挺好的分享,结果到楼主这里挑出来一个就说什么 "传统 C++库" 被 "游戏页" 打的找不到北,搞个大新闻。。

    我贴出来开源地址: https://github.com/RobloxResearch/SIMDString
    人家说得很清楚:这是为 3D 程序的使用场景做的优化,其他使用场景性能可能没那么好,甚至比 std::string 更差。
    yulon
        19
    yulon  
       87 天前
    但凡你写过几年 C++,标准库的实现从来都是通用而非性能。

    你像富文本 GUI 要是直接用 std::string ,内存还不炸了?
    lambdaq
        20
    lambdaq  
       87 天前   ❤️ 1
    路过。。其实这也是为啥 C++ 生态支离破碎的原因。。连字符串这种基础得不能再基础的东西都要发明 n 个轮子争论半天。。所以最后不同的库连最基本的数据结构都不互相兼容。
    cxxnullptr
        21
    cxxnullptr  
       87 天前
    OP 能贴一下开源的地址吗,找了半天没找到
    glfpes
        22
    glfpes  
       87 天前   ❤️ 18
    建议 OP 去干自媒体,引战拿流量的本领有专业风范。
    julyclyde
        23
    julyclyde  
       87 天前
    @tool2d 没有 SIMD 的机器现在还存在吗?
    julyclyde
        24
    julyclyde  
       87 天前   ❤️ 1
    @tool2d std::string 是否由模板实现的那无所谓啊,那只是个实现
    STL 是指 vector<T>那类东西啊
    CrazyRain0001
        25
    CrazyRain0001  
       87 天前
    c++有性能需求的一般都要自己优化吧。不同 CPU 有不同的接口,SIMD 在某些 arm 上可能还不如编译优化,Inter 的用 IPP 也比 SIMD 直接。最终还要看业务逻辑,这个 stl 没法搞
    besto
        26
    besto  
       87 天前
    up 不会觉得 GPU 是 SIMD 吧(手动狗头)
    across
        27
    across  
       87 天前 via iPad
    游戏行业大项目一般不用 std ,这个是兼顾各方平衡用的库,性能当然不突出,最多当标杆参考。
    游戏里 json 最常见是 rapidjson ,腾讯 milo yip 写的,快十来年了吧,simd 就有用上,3A 大项目很多都用这个库。最近字节也出了一个库,号称比 rapidjson 快来着,还没仔细看过。
    encro
        28
    encro  
       87 天前   ❤️ 1
    标准库需要考虑完备性,兼容性,统一性和异常处理等,
    你只要砍掉任意需求,节省这方面的性能开支,当然能提升性能。

    当我们谈论计算机程序性能时,我们需要同时考虑原因和代价等,这是一个有经验程序员都应该知道的。

    发这种文章,不分析原因,
    要么作者在盲人摸象、道听途说,
    要么就是为了哗众取宠而故意断章取义、混淆是非。
    phiysng
        29
    phiysng  
       87 天前
    领域优化的实现比通用实现快很奇怪吗
    qieqie
        30
    qieqie  
       87 天前 via iPhone
    你猜为啥他的 benchmark 要比 32B 而不是 24B 以下(gcc/clang sso),或者 32B(neon, sse 宽寄存器),64B(AVX2)以上呢。
    Skifary
        31
    Skifary  
       87 天前   ❤️ 9
    多一点包容吧,大多数人应该都有“哇,我发现了一个好厉害的东西,我要去炫耀一下我的发现”的时期,学习和成长都是这么慢慢来的。
    qieqie
        32
    qieqie  
       87 天前 via iPhone   ❤️ 1
    首先我没有看这个库源代码和视频,根据常识盲给几个结论:
    对于小于 24 字节的 string ,编译器在 gcc5/clang6 之后的实现都会有明显性能提升,但是这个 simd string 不会甚至略降(simd 要做 align 和 padding )。
    对于大于 32 字节的 string ,simd string 在不支持 avx2 寄存器的环境下都会成倍降低或者 fallback 。
    nulIptr
        33
    nulIptr  
       87 天前
    笑死,你能说下哪个正经项目用的 std::string 吗
    bashbot
        34
    bashbot  
       87 天前   ❤️ 1
    @nulIptr #33

    我司做命令行工具的,EDA 行业软件,就是用 std::string ,不然用 char*吗。
    能用 STL/std 就不用其他,这个是我们开发的惯例。使用第三方库和代码涉及兼容性、后期维护、授权问题,严重影响开发效率。至于什么字符串性能,加机器就能解决的问题,根本不用考虑。
    想想要兼容十年前的服务器硬件和 Arm 最新的硬件,要兼容 Centos6 和 RHEL6~8 ,选一个第三方库前期调研得投入多少精力。老板们常说的话是:代码重构?没有 10 倍以上性能提升就不要考虑重构。

    所以什么谁打败谁,完全是看需求,符合使用场景的就是好的,不好的话就是用的人没用好。
    dabaibai
        35
    dabaibai  
       87 天前
    15 年前做游戏 都是自己写 string 写字符串渲染 ,字符编码转换等

    15 年后的今天 这些东西都进引擎了 也没必要纠结了 用就完了
    msg7086
        36
    msg7086  
       87 天前 via Android
    做游戏可以强迫用户换 CPU ,做标准库也可以强迫用户换 CPU 吗?不如换用 avx512 ,人人都得用志强或者 zen4 ,速度快还能拉动 GDP 。
    pi1ot
        37
    pi1ot  
       87 天前
    这一行里不会有人拿 std::string 做性能对手,就像做浏览器的没人拿 IE 比性能一样。
    openmm
        38
    openmm  
       87 天前
    吓死了,光看标题还以为出大事,c++又被吊打了
    tyzandhr
        39
    tyzandhr  
       87 天前 via Android
    所以写 c++的诸位都用的是什么字符串库?莫非用的是 char 数组?
    tool2d
        40
    tool2d  
    OP
       87 天前
    @tyzandhr 用自己写的短字符优化的库,理论上 std::string 算法没问题,有问题的是默认的内存分配器,实在很不给力。
    tool2d
        41
    tool2d  
    OP
       87 天前
    @icyalala "人家说得很清楚:这是为 3D 程序的使用场景做的优化,其他使用场景性能可能没那么好,甚至比 std::string 更差。"

    这仅仅是你的看法,我个人看法和你刚好相反,32 字节优化后的字符串库,对于覆盖 90%的应用场景都够了。剩下 10%就用作者视频里提到的 readonly 字符串。

    无脑用 std::string ,会导致内存碎片过多,实在很不推荐。
    icyalala
        42
    icyalala  
       87 天前   ❤️ 5
    @tool2d 这不是我的个人看法,这是你的分享里原作者的看法,原话就是这样
    Limitations:...
    SIMDString is designed and benchmarked for the usage patterns found in games and other real-time 3D applications. It may perform less well and even underperform std::string for applications with different usage patterns.
    hazardous
        43
    hazardous  
       87 天前
    这就是 C++的优势啊,追求极致的性能,有特殊优化的需求那就自己去实现。其它语言不这么干的那就是对性能要求不够高。
    tyzandhr
        44
    tyzandhr  
       87 天前 via Android
    @tool2d 你是说 glibc ?
    jmc891205
        45
    jmc891205  
       87 天前
    @bashbot EDA tool 不需要大量处理字符串,std::string 不会成为性能瓶颈
    superares
        46
    superares  
       87 天前
    要不试试用 AVX512 ?估计更快
    dazhangpan
        47
    dazhangpan  
       87 天前
    对于任何一名做底层软件的资深开发者来说,游戏业这点优化,小儿科啦
    nightwitch
        48
    nightwitch  
       87 天前 via Android
    只比时间不比空间吗。做 simd 肯定需要 padding 到字节对齐的
    nmap
        49
    nmap  
       87 天前
    std::string 性能不行是众所周知吧
    LuckyPocketWatch
        50
    LuckyPocketWatch  
       86 天前
    首先,std::string 是一个标准。不同的编译器的 std::string 也是不一样的

    其次,std::string 性能不行我从来不认可的,一个字符处理能够兼顾通用性和性能,各版本的 std::string 已经做到非常好,至少,vs 和 gcc 的都是如此

    最后也是最重要的,说 xxx 的效率碾压 std::string,这里没有说清楚一个很重要的问题是,你在测试前加了多少定语?如果定语足够多,我也可以写出一款碾压 std::string 的字符串处理函数

    附:你说开源,不贴个 github 或 gitlab 的地址么,实在不行 gitee 也行,你贴个油管地址我不是很认可。。
    ToBeHacker
        51
    ToBeHacker  
       86 天前
    密集应用场景下做特定优化不是常识么

    你拿一个特定优化的跟一个标准库打,有啥意义么,性能指标都不一样好么
    DefoliationM
        52
    DefoliationM  
       86 天前   ❤️ 3
    可以看看 op 的历史发帖,很多我都觉得挺逆天的
    leimao
        53
    leimao  
       86 天前 via iPhone
    和世界上任何一件事物一样,C++语言及其标准库的确有各种各样的缺点。但是评价他需要客观,建议少发一些误导性比较强的标题和帖子。
    DCounter
        54
    DCounter  
       86 天前
    @msg7086 老哥说的对。具体实现方式和其使用场景是强相关的,脱离了这个前提还有啥可比性?楼主真是引战好手
    levelworm
        55
    levelworm  
       86 天前 via Android
    我记得游戏界好像很早就是自己开发这种工具,比如 EA 的那套。迭代了很多年了,游戏专用,肯定比标准库的好吧。
    mingl0280
        56
    mingl0280  
       86 天前 via Android   ❤️ 2
    麻烦 op 不要把混 b 站和逼乎发的逆天言论拿到 v2 来秀智商
    ragnaroks
        57
    ragnaroks  
       86 天前
    任何语言的标准库的意义是当你需要某个扳手的时候有个能用的扳手,至于好不好用那才是第三方库的意义
    Dryopithecine
        58
    Dryopithecine  
       86 天前
    @mingl0280 其实我感觉知乎上厉害的 C++使用者挺多的,比 V2EX 要多
    antonius
        59
    antonius  
       86 天前
    @across simdjson 了解一下
    antonius
        60
    antonius  
       86 天前
    @nulIptr 也不是不能用。我们的商业项目(game project, inhouse engine)就用 stl ,包括 std::string 。但性能要求比较高的场景下需要注意内存管理,比如避免频繁申请释放内存,减少内存碎片等等。性能问题需要做 profiling 的,特定问题特定解决。
    NoAnyLove
        61
    NoAnyLove  
       86 天前
    又是标题党。STL 主要针对的是通用情景,并且尽可能做到最大的兼容性,没必要和针对特定情境和特定架构优化的项目相比。

    另外,开源项目中存在一些没有优化的地方有什么好奇怪的,慢慢来嘛,又不是拿工资还看 KPI
    cnLittleYu
        62
    cnLittleYu  
       86 天前 via Android
    很多 STL 实现被吐槽慢很多年了,经常看到项目用自己写的 string 来替换 STL ,其实不算新鲜事了。
    游戏工程上牛逼的实现非常多,比如经典的快速平方根。
    SIMD 在游戏领域用得比较多,之前看 unity 源码,它很多的矩阵运算都是用 SIMD 来优化。但 STL 无论是历史包袱还是通用性的要求,是不太可能为了极限性能去做这种改变的。

    没有孰优孰劣,看场景罢了。
    FrankHB
        64
    FrankHB  
       85 天前
    进来前就在想怕又是个 allocator 拎不清楚的,结果对比一个直接把 allocator 写脸上了……药店碧莲行么?
    且不提 COW 的 std::basic_string ( C++11 已经寄了……那年头会折腾的都知道 vstring 和 rope 罢)同样的操作可能反过来吊打,你依赖 SIMD 就已经是可移植性上投降了。
    std::string (还不是 std::basic_string )原则上不可能被干掉的最大槽点是污染 stdexcept 外加 ABI (但除了 Itanium 的 mangling 开洞之类的琐碎问题外,根本上这是用户对 ABI 假设普遍自己作死,不是 string 的问题),看不出这个的还真没资格写玩具碰瓷。

    @pocarisweat string 本来就是纯数学概念,虽然定义依赖 alphabet 却没所谓字符的意思,你还是先叫 C++的 vector 滚粗吧。
    本来叫 vector 的东西 C++的叫 array ,本来叫 string 的东西 C++叫 vector (还硬塞了个 valarray ),然后扯了坨 char_traits ,就这笑话了。
    虽然始作俑者应该是 C 硬把 B 的 vector 叫 array ,然后本来叫 array 的东西( C 表达不了) C++里叫[unordered_]map (严格来说是实现了 operator[]的 concept ,vector/basic_string 也算),本来叫 map 的东西叫 transform……乱成一锅粥。
    ALGOL 厨二数学学渣祸害了不知道多少人。

    @nullptr 比如屑 LLVM 。还不只是 std::string 。
    开个_GLIBCXX_DEBUG 不重新编译都能炸了。
    litbear
        65
    litbear  
       85 天前
    懂点儿,又不多,刷 hacker news 看到个标题,就添油加醋拿到简中社区装 13 。甚至不知道“传统 std::string”这几个字是什么意思
    Chinsung
        66
    Chinsung  
       85 天前
    没搞懂,大部分语言集合排序的实现都是快排,我写个桶排或者插排在某些数据下吊打了默认的快排实现,然后也可以发一个这样的帖,是这个意思吗?
    tontyoutoure
        67
    tontyoutoure  
       85 天前 via Android
    profiling 下来发现热点在 stdstring 上的时候,花个一半天换个合适的第三方库不就好了么,有啥好吵的么,你又是 c++又是性能的,不会没有先 profiling 再讲话的习惯吧,不会吧不会吧
    adian
        68
    adian  
       80 天前
    反向搅屎棍,激起大家表达欲是吧
    macha
        69
    macha  
       74 天前
    哪里不行优化哪里,大部分业务代码其实对性能要求不高,对容易懂,大家都能上去改的要求更高一些。
    关于   ·   帮助文档   ·   博客   ·   nftychat   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   2561 人在线   最高记录 5556   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 50ms · UTC 13:12 · PVG 21:12 · LAX 06:12 · JFK 09:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.