C++高性能并行编程与优化 - 课件 - 05 C++11 开始的多线程编程
的过程中会暂时 unlock() 这个锁。 案例:实现生产者 - 消费者模式 • 类似于消息队列…… • 生产者:厨师,往 foods 队列里推送食品 ,推送后会通知消费者来用餐。 • 消费者:等待 foods 队列里有食品,没有 食品则陷入等待,直到被通知。 条件变量:将 foods 队列封装成类 std::condition_variable 小贴士 1. std::condition_variable0 码力 | 79 页 | 14.11 MB | 1 年前3基于 Rust Arrow Flight 的物联网和时序数据传输及转换工具 霍琳贺
taosX - 物联网数据接入问题 • 多种不同协议数据对接,开发复杂度高 • 模块之间关联性不高但模块组成复杂,可维护性差 • 大量设备大量数据归集存储,存储压力大 • 数据总线 / 消息队列消息接入,定制化程度要求高 • 数据业务逻辑自定义需求强 • 一定的实时数据分析能力 taosX - 功能路线图 集群运维 数据接入 流式处理 流式处理 数据分享 开放平台 • Backup/Restore0 码力 | 29 页 | 2.26 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 06 TBB 开启的并行编程之旅
任务域:指定使用 4 个线程 嵌套 for 循环 嵌套 for 循环:死锁问题 死锁问题的原因 • 因为 TBB 用了工作窃取法来分配任务: 当一个线程 t1 做完自己队列里全部的工 作时,会从另一个工作中线程 t2 的队列 里取出任务,以免 t1 闲置浪费时间。 • 因此内部 for 循环有可能“窃取”到另一个 外部 for 循环的任务,从而导致 mutex 被重复上锁。 解决 1 9 14 10 15 13 5 解决 2 :线程数量不变,但是用一个队列分发和认领任务 • 但是线程数量太多会造成调度的 overhead 。 • 所以另一种解法是:我们仍是分配 4 个线程,但 还是把图像切分为 16 份,作为一个“任务”推送到 全局队列里去。每个线程空闲时会不断地从那个 队列里取出数据,即“认领任务”。然后执行,执行 完毕后才去认领下一个任务,从而即使每个任务 线程需要保存上下文的开销。但是需要我们管理 一个任务队列,而且要是线程安全的队列。 struct Task { int x0, y0; int nx, ny; }; std::queueq; 1 2 3 4 解决 3 :每个线程一个任务队列,做完本职工作后可以认领其他线程的任务 工作窃取法( work-stealing ) 原始的单一任务队列 解决 4 :随机分配法(通过哈希函数或线性函数) 0 码力 | 116 页 | 15.85 MB | 1 年前3Rust 异步并发框架在移动端的应用 - 陈明煜
Local queue Tokio 采用了如右图这种 GMP 模式: • 一核可以绑定多线程,每个线程拥有一个 Worker ,每个 Worker 拥有一个任务队列 • 但线程拥有相同优先级 • Worker 只持有一个本地 FIFO 队列 移动端诉求:优先级 • 任务区分优先级: UI 显示 vs 后台下载 • 大小核调度 Incompatibility of the third party of service 任务优先级调度 对框架内的工作线程设置优先级,使其 拥有不同权重。 • 由 Kernel 决定调度时间 • 高优先级任务由高权重线程调度, 以此获得更多执行时间 • 全局队列区分高低优先级 Task priority and quality of service 高权重线程 低权重线程 task …. task …. Global queue task Local0 码力 | 25 页 | 1.64 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 07 深入浅出访存优化
浪费读取的带宽。这样的条件实在有点苛刻,毕 竟小彭老师的电脑还不支持 AVX512 。 • 可以用 _mm_stream_si32 指令代替直接赋值的 写入,他能够绕开缓存,将一个 4 字节的写入操 作,挂起到临时队列,等凑满 64 字节后,直接写 入内存,从而完全避免读的带宽。 • 可惜这货只支持 int 做参数,要用 float 还得转换 一下指针类型, bitcast 一下参数。 stream 的特点:不会读到缓存里 • 才应该用 stream 指令。 4 倍矢量化的版本: _mm_stream_ps • _mm_stream_si32 可以一次性写入 4 字 节到挂起队列。而 _mm_stream_ps 可以 一次性写入 16 字节到挂起队列,更加高 效了。 • 他的第二参数是一个 __m128 类型,可以 配合其他手写的 SIMD 指令使用。 • 不过, _mm_stream_ps 写入的地址必须 b 污染了一级缓存,导 致预取效果不好,我们用直写指令试试看 。 使用直写指令 • 反而更加更加慢了? • 可能是因为直写的时间点过于分散了,因 为中间还夹杂着加法的运算,导致写入挂 起队列指令太长, CPU 放弃了合并的直写 。 • 我们把 stream 指令全部合并到一个时间 点附近看看。 让直写指令在时空上尽可能靠拢 • 把 res 变成数组暂时存一下,最后再一次 性用0 码力 | 147 页 | 18.88 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 08 CUDA 开启的 GPU 编程
1>>>() 后,并不 会立即在 GPU 上执行完毕,再返回。实际上只是把 kernel 这个任务推送到 GPU 的执行队列上,然后立即 返回,并不会等待执行完毕。 • 因此可以调用 cudaDeviceSynchronize() ,让 CPU 陷 入等待,等 GPU 完成队列的所有任务后再返回。从而 能够在 main 退出前等到 kernel 在 GPU 上执行完。 定义在 GPU 上的设备函数0 码力 | 142 页 | 13.52 MB | 1 年前3CeresDB Rust 生产实践 任春韶
Rust 生产实践 生产实践 – Tokio 为什么使用 Tokio ? 1. 业界使用最广泛,测试齐全。 2. Tokio 支持 async/await ,提供了高效的异步锁、异步队列等。 3. Tokio 社区支持好。 生产实践 – Tokio Rust future preemption https://docs.rs/tokio/latest/tokio/#0 码力 | 22 页 | 6.95 MB | 1 年前3夏歌-使用Rust构建LLM应用
收到 规定好的 Slash 开头的 telegram command ,就预启动不同的 Prompt "0.1.0" 基于 ChatGPT 的 Telegram 机器人 当收到消息的时候,就按照预 设的 system_prompt 使用 GPT3.5 调用 OpenAI , 并把结果返回。 "0.1.0" 基于 ChatGPT 的 Telegram 机器人 在 ocr0 码力 | 36 页 | 38.31 MB | 1 年前3Rust分布式账务系统 - 胡宇
1 2 3 4 ● 1. 接受转账请求,转换成 events ● 2. 将 events 送入 Raft 共识,等待 events 被多数节点保存 ○ 共识:基于 raft-rs 的可靠消息队 列 ○ 存储: Rocksdb with Rust 账户层: Auticuro 分布式账务系统 1 2 3 4 ● 1. 接受转账请求,转换成 events ● 2. 将 events0 码力 | 27 页 | 12.60 MB | 1 年前3
共 9 条
- 1