应用 waPC (rust) 做软件测试工具
*\/info_modify_req”.into(),echo_req_js on); reg.insert(“\/v2\/matches\/.*\/info_modify_res”.into(),echo_res_jso n); reg.insert(“\/v2\/matches\/.*\/info_fiddler_ab”.into(),do_nothing); } waPC in rust in HTTP(MITM) golang.org\r\nConnection: close\r\nUser-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; de-de)\r\n\r\ n"), HttpBody:vec![], ProxyUrl:String::from("") }0 码力 | 30 页 | 2.50 MB | 1 年前3绕过conntrack,使用eBPF增强 IPVS优化K8s网络性能
chain • Pros • Iptables is widely adopted in popular Linux distributions • Cons • O(N^2) in control plane / O(N) in data plane • Poor in scheduling algorithm • Iptables rules are difficult to debug from local-in to PREROUTING • The challenges • Skb’s pointer to route is NULL during PREROUTING • No de-fragment is done during PREROUTING IPVS bypass conntrack (con.) • Egress • Original way • Nf local-out SNAT in TC egress • Do reverse SNAT in TC ingress Tc egress Hit eBPF map? Does SNAT nic nic Y N • How IPVS talks with eBPF program? • eBPF map id is passed to IPVS module • Ip_vs_new_conn() inserts0 码力 | 24 页 | 1.90 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 09 CUDA C++ 流体仿真实战
cudaBoundaryModeTrap :一旦越界就奔溃。 • cudaBoundaryModeClamp :越界则把 xyz 坐标钳 制( clamp )到原本的数组大小范围内,比如把 - 100 钳制到 0 , n+100 钳制到 n-1 。 • cudaBoundaryModeZero :对于读来说越界会读取到 0 ;对于写来说越界会放弃写入,不修改数组中的任 何值。 • 表面对象保障了高效的访存,并且自动判断越界,体 • cudaAddressModeBorder :超出范围就用零代替 • 示意: 00 | ABCDE | 00 • cudaAddressModeWrap :重叠模式(循环) • 示意: DE | ABCDE | AB • cudaAddressModeMirror :镜像模式 • 示意: BA | ABCDE | ED CUDA 纹理对象:封装 • 其中 cudaTextureFilterMode0 码力 | 58 页 | 14.90 MB | 1 年前3THE FIRST EXPLORATION OF PROJECT SPARROW
com/microkernel-in-operating-systems.html I. Background . Source: https://os.inf.tu-dresden.de/Studium/MkK//SS2021/01_intro.pdf Architecture & Design 1.2 L4 Overview I. Background https://en0 码力 | 68 页 | 13.14 MB | 1 年前3Bringing Existing Code to CUDA Using constexpr and std::pmr
|void add_cpu(int n, float* x, float* y) { for (int i = 0; i < n; i++) y[i] = x[i] + y[i]; } TEST_CASE("cppcon-0", "[CUDA]") { int N = 1 << 20; float* x = new float[N]; float* float* y = new float[N]; for (int i = 0; i < N; i++) { x[i] = 1.0f; y[i] = 2.0f; } add_cpu(N, x, y); delete[] x; delete[] y; } An Even Easier Introduction to CUDA |TEST_CASE("cppcon-1", "[CUDA]") { int N = 1 << 20; float* x; float* y; cudaMallocManaged(&x, N*sizeof(float)); cudaMallocManaged(&y, N*sizeof(float)); // … cudaFree(x);0 码力 | 51 页 | 3.68 MB | 5 月前3C++高性能并行编程与优化 - 课件 - 13 C++ STL 容器全解之 vector
类型的动态数组 a : • vectora; vector 容器:构造函数和 size • vector 可以在构造时指定初始长度。 • explicit vector(size_t n); • 例如,要创建一个长度为 4 的 int 型数组 : • vector a(4); • 之后可以通过 a.size() 获得数组的长度。 • 比如右边这段代码会得到 4 。 vector a(4); • 会得到长度为 4 元素全为 0 的数组。 • vector(initializer_list list); • explicit vector(size_t n); vector 容器:构造函数 • 这在对于只能用花括号初始化的类成员来说,就 有很大问题: • vector a{4}; • 会得到长度为 1 只有一个元素 4 的数组。 • vector (4); • 会得到长度为 4 元素全为 0 的数组。 • vector(initializer_list list); • explicit vector(size_t n); vector 容器:构造函数 • 这在对于只能用花括号初始化的类成员来说,就 有很大问题: • vector a{4}; • 会得到长度为 1 只有一个元素 4 的数组。 • 0 码力 | 90 页 | 4.93 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 07 深入浅出访存优化
原始的代码第一个循环体执行 a[i] = a[i] * 2 ,等乘法全 部结束了以后,再来一个循环体执行 a[i] = a[i] + 1 。 • 因为第一遍循环过了 1GB 的数据,执行到 a[n-1] 时 ,原本 a[0] 处的缓存早已失效,因此第二遍循环开始 读取 a[0] 时必须重新从主内存读取,然后再次写回主 内存。 • 这种代码在主内存看来, CPU 做的事情相当于:读 + 案例:一维 jacobi 迭代 • 一些物理仿真中,常用到这种形式的迭代法: • for (i=0...n) b[i] = a[i + 1] + a[i - 1]; // 假装是 jacobi • swap(a, b); // 交换双缓冲 • for (i=0...n) b[i] = a[i + 1] + a[i - 1]; // 假装是 jacobi • swap(a, b); 第 5 章:内存分配与分页 vector :写入两次,时间都是一样的(理所当然) malloc :写入两次,第一次明显比第二次慢? new int[n] :和 malloc 一样,写入两次,第一次明显比第二次慢? new int[n]{} :后面加个花括号,就和 vector 一样,两次一样快了 结论 • 原理,当调用 malloc 时,操作系统并不会实际分配那一块内存,而是将这一段内存标记0 码力 | 147 页 | 18.88 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 06 TBB 开启的并行编程之旅
time-efficiency )与工作量复杂度( work-efficiency ) • 在“小学二年级”算法课里,我们学过复杂度的概念,意思是算法执行所花费的时间取决于数据量 的大小 n ,比如 O(n²) 表示花费时间和数据量的平方成正比。 • 对于并行算法,复杂度的评估则要分为两种: • 时间复杂度:程序所用的总时间(重点) • 工作复杂度:程序所用的计算量(次要) • 这两个指 至有牺牲工作复杂度换取时间 复杂度的情形。 • 并行算法的复杂度取决于数据量 n ,还取决于线程数量 c ,比如 O(n/c) 。不过要注意如果线程 数量超过了 CPU 核心数量,通常就无法再加速了,这就是为什么要买更多核的电脑。 • 也有一种说法,认为要用 c 趋向于无穷时的时间复杂度来衡量,比如 O(n/c) 应该变成 O(1) 。 映射( map ) 1 个线程,独自处理 8 个元素的映射,花了 个元素的映射,花了 8 秒 用电量: 1*8=8 度电 结论:串行映射的时间复杂度为 O(n) ,工作复杂度为 O(n) ,其中 n 是元素个数 并行映射 4 个线程,每人处理 2 个元素的映射,花了 2 秒 用电量: 4*2=8 度电 结论:并行映射的时间复杂度为 O(n/c) ,工作复杂度为 O(n) ,其中 c 是线程数量 封装好了: parallel_for 面向初学者: parallel_for0 码力 | 116 页 | 15.85 MB | 1 年前3C++高性能并行编程与优化 - 课件 - 14 C++ 标准库系列课 - 你所不知道的 set 容器
那如果我确实需要让 set 迭 代器向前移动 3 格怎么办? • 可以调用三次 ++ 运算,实 现和 + 3 同样的效果。 • vector 迭代器的 + n 复杂度 是 O(1) 。而 set 迭代器模 拟出来的 + n 复杂度为 O(n) 。虽然低效,但至少可 以用了。 std::next 等价于 + • 但是这样手写三个 ++ 太麻烦了 ,而且是就地操作,会改变迭代 器本身。 • • 因此标准库提供了 std::next 函 数,他的内部实现相当于这样: • 没错,他会自动判断迭代器是否 支持 + 运算,如果不支持,会 改为比较低效的调用 n 次 ++ 。 std::advance 等价于 += • 刚刚的 std::next 会返回自增后迭代器 。 • 还有 std::advance 会就地自增作为引 用传入的迭代器,他同样会判断是否支 持 += 来决定要采用哪一种实现。 不会改变原迭代器。 • advance 相当于 += , next 相当于 + 。 next 和 advance 同样支持负数 • next 的第二个参数 n 通常是正 数,表示向前走的距离。 • 如果迭代器类型是双向迭代器。 next 的第二个参数 n 还可以是 负数,这时他会让迭代器往前走 一段距离,例如: • std::next(it, -3) 相当于 it - 3 。 • 还可以用另一个专门的函数0 码力 | 83 页 | 10.23 MB | 1 年前3Lock-Free Atomic Shared Pointers Without a Split Reference Count? It Can Be Done!
Load 24.8 n 16n 16n 31n 34n Store 29.8 n 19n 19n 34n 40n Store-delete 63.0 n 44n 44n 59n 14.9u Deamortized 1% 50% 99% 99.95% Load 30.0 n 20n 20n 34n 35n Store 30.2 n 20n 20n 34n 35n Store-delete Store-delete 62.4 n 47n 47n 88n 163n0 码力 | 45 页 | 5.12 MB | 5 月前3
共 43 条
- 1
- 2
- 3
- 4
- 5