Effective STL - 05 - Functor
Functor条款38:把仿函数类设计为用于值传递C 中的 qsort 使用的 函数指针 就是指针的拷贝,因此是一个默认的值传递。 因为函数对象以值传递和返回,你的任务就是确保当那么传递(也就是拷贝)时你的函数对象行为良好。这暗示了两个东西。第一,你的函数对象应该很小。否则它们的拷贝会很昂贵。第二,你的函数对象必须单态(也就是,非多态)——它们不能用虚函数。 不是所有的仿函数都是小的、单态的。函数对象比真的函数优越的的原因之一是仿函数可以包含你需要的所有状态。有些函数对象自然会很重,保持传这样的仿函数给STL算法和传它们的函数版本一样容易是很重要的。(像之前提到的算法中 Algorithms ,Points 类就使用了 PointsAverage 来保存对应的状态,我的实现使用了 lambda 和引用来保存求和的结果) 1234567891011121314151617181920212223242526272829/*使用 Bridge 模式*/template<typename T> // 用于修改的BPFCclass BPFCImpl: public una...
Effective STL - 04 - Algorithms
Algorithms条款30:确保目标区间足够大123456789101112131415vector<int> v = {0, 1, 2, 3, 4, 5, 6, 7};cout << v << endl;// 对于使用区间的函数, 注意预先分配空间vector<int> v2;v2.reserve(v.size());transform(v.begin(), v.end(), back_inserter(v2), [] (int& a) { return a * 2;});cout << v2 << endl;v2.reserve(v.size() * 2);transform(v.begin(), v.end(), back_inserter(v2), bind(multiplies<int>(), placeholders::_1, 2));cout << v2 << endl; 注意:back_ins...
Effective STL - 03 - Iterator
Iterator条款26:尽量用iterator代替const_iterator,reverse_iterator和const_reverse_iterator 123456graph A[iterator] --> B[const_iterator]A[iterator] --> C[reverse_iterator]C[reverse_iterator] --> D[const_reverse_iterator]C[reverse_iterator] -->|base| A[iterator]D[const_reverse_iterator] -->|base| B[const_iterator] iterator 能够比 const_iterator 有更好的泛化性能,特别是对于 insert 、erase 函数,他们只支持 iterator 而不支持 const_iterator。 我们已经有足够的理由相信应该尽量使用iterator取代const或者reverse类型的迭代器: insert和erase的一些版本要求iterator...
Effective STL - 02 - Vector and String
Vector and String条款13:尽量使用vector和string来代替动态分配的数组无论何时,你发现你自己准备动态分配一个数组(也就是,企图写“new T[…]”),你应该首先考虑使用一个vector或一个string。 坦白地说,我想到了一个(也是唯一一个)用vector或string代替动态分配数组会出现的问题,而且它只关系到string。很多string实现在后台使用了引用计数(参见条款15),一个消除了不必要的内存分配和字符拷贝的策略,而且在很多应用中可以提高性能。事实上,一般认为通过引用计数优化字符串很重要,所以C++标准委员会特别设法保证了那是一个合法的实现。 唉,一个程序员的优化就是其他人的抱怨,而且如果你在多线程环境中使用了引用计数的字符串,你可能发现避免分配和拷贝所节省下的时间都花费在后台并发控制上了。(细节请参考Sutter的文章《Optimizations That Aren’t (In a Multithreaded World)》[20]。)如果你在多线程环境中使用引用计数字符串,就应该注意线程安全性支持所带来的的性能下降问题。 条款14:...
Effective STL - 01 - Containers
Containers条款 1 仔细选择你的容器 vector是一种可以默认使用的序列类型,当很频繁地对序列中部进行插入和删除时应该用list,当大部分插入和删除发生在序列的头或尾时可以选择deque这种数据结构 连续内存容器(也叫做基于数组的容器)在一个或多个(动态分配)的内存块中保存它们的元素。如果一个新元素被查入或者已存元素被删除,其他在同一个内存块的元素就必须向上或者向下移动来为新元素提供空间或者填充原来被删除的元素所占的空间。这种移动影响了效率(参见条款5和14)和异常安全(就像我们将会看到的)。标准的连续内存容器是vector、string和deque。 基于节点的容器在每个内存块(动态分配)中只保存一个元素。容器元素的插入或删除只影响指向节点的指针,而不是节点自己的内容。 你要把迭代器、指针和引用的失效次数减到最少吗?如果是,你就应该使用基于节点的容器,因为在这些容器上进行插入和删除不会使迭代器、指针和引用失效(除非它们指向你删除的元素)。一般来说,在连续内存容器上插入和删除会使所有指向容器的迭代器、指针和引用失效。 你需要具有有以下特性的序列容器吗:...
使用zerotier实现免费上网
原理本文提到的操作需要使用一台机器进行中转,这个机器可以是服务器,也可以是自己工位上的 Windows 机器。同时,这个机器上还必须打开了 Clash、V2Ray、SSR 之类的代理,并拥有一个端口号。 基本原理:假设我们在宿舍有一台笔记本,称为 Alice,简称为 A;在工位上有一台电脑,称为 Bob,简称为 B。A 只能访问校园网的网站,例如 csu.edu.cn;B 能够访问互联网,例如 baidu.com。那么,如果我们能够实现 A 的 https 请求通过 B 进行转发,然后再由 B 转发回 A,也就实现了让 A 上网。如图, 从密码学角度来想,Bob 就是 Alice 和 Internet 的中间人,它可以获取二者通信的所有内容,所以我们要保证 Bob 一定是可信的。如果 Bob 不可信,我们还可以通过 https 进行通信,https 的所有信息都是被加密过的,如果 Bob 没有解密私钥,他就无法窃取机密信息。如何进行私钥分发,保证私钥的隐私性和不篡改性?一般是通过第三方的公证机构,所以 https 的认证证书是收费的。 要实现以上的连接,我们需要两个工具: 实...
llama2
LLaMa2Transformer IntroductionArchitecturetransformer 最主要的结构就是这张图: 在纯 Encoder 或者纯 Decoder 的架构中,会变成只有左边的 transformer block 的结构,但是区别在于 Multi-Head Attention 是否存在 mask。Encoder-only 架构为了获取每一个 token 的完整上下文,因此没有对应的 mask;Decoder-only 架构为了让每一个 token 只能注意到它前面的 token,因此会存在一个从前往后的 mask,即生成的 $QK^T$ 矩阵(shape 为 $n_{tokens} \times n_{tokens}$)是一个下三角阵。 llama2 的 QK^T 矩阵注意力输出,Decoder 架构,因此是一个下三角阵 Encoder-DecoderTransformer-based Encoder-Decoder Models Transformer 是 Encoder-Decoder 结构的一种,这是为了解决在 NLP 中输入和输出长度不...
侯捷CPP-STL
课件截图容器 list list 是一个双向链表,如果需要写一个 MyList ,那就可以参考 list 的写法。 注意到这里的 bidirectional_iterator_tag ,这表明 list 的迭代器是一个双向迭代器,只支持图中展示的四个操作。但是 vector 的迭代器是 RandomAcessIterator ,可以支持随机访问,因此能够使用 std::sort ,而不需要本身带有一个 sort 函数。 在之前的黑马程序员里也讲过这个编译器优化案例。 list 的迭代器在 2.9 和 4.9 中存在一定的不同,2.9 中的指针类型和引用类型都是不固定的,可以任意指定,但是 4.9 中的都与数据成员 _Tp 一致。同时,指针类型也通过继承实现了自带的 next 和 prev 。(可以用于以后的实现) 但是目前 MSVC 的实现并不一样,而是使用了一个 Node_Ptr ,其等于 typename pointer_traits<type-parameter-0-1>::template rebind<_List_node<_Value...
Caffe2 中 float32 与 float16 的转换
generated by Copilot and translated by DeepL 这段 C++ 代码是一个名为 cpu_float2half_rn 的函数,用于将单精度浮点数(32 位)转换为半精度浮点数(16 位)。该函数将浮点数作为参数,并返回一个 float16 对象。转换过程涉及多个步骤,包括处理 NaN 和无穷大等特殊情况,从输入中提取符号、指数和尾数,以及四舍五入到最接近的偶数。 函数首先声明了一个 float16 对象 ret,用于保存转换结果。然后使用 static_assert 来确保无符号 int 和 float 的大小相同。这一点很重要,因为函数使用位操作来处理 float 的二进制表示,这需要将 float 解释为无符号整数。 函数使用 reinterpret_cast 获得指向 float 二进制表示形式的指针。然后创建该二进制表示的副本,屏蔽符号位,得到浮点数 u 的绝对值。 函数会处理特殊情况。如果 u 大于 0x7f800000,输入值为 NaN,函数会将结果设置为特殊的 NaN 值并返回。如果 u 大于 0x477fefff 或小于 ...
ORT 模型部署
Deploy ORT modelonnxruntime-inference-examples/mobilenet.ipynb at main · microsoft/onnxruntime-inference-examples 详细记录YOLACT实例分割ncnn实现 真正部署模型,不应该把后处理包括在模型推理中,这会影响模型在GPU上的部署,性能也不一定会好。这里的后处理,不仅仅是model(input) 之后的,也可以是作者放在模型推理过程中,但是实际上可以归为后处理的部分。 判断函数是否在ONNX trace的过程中:torch.onnx.is_in_onnx_export() 。 ONNX to TF Torch to ONNX torch不支持F.grid_sample 算子。从ONNX支持的算子列表来看,opset=16 时,可以直接使用grid_sampler 而不需要手动设置符号函数。 12345678910111213141516171819202122232425262728# https://github.com/pytorch/pyt...