memcpy和vector的搭配使用

该博客讨论了如何将CUDA中的torch::Tensor转换为vector,并强调了转换过程中需要注意的事项,包括确保vector已初始化大小,将Tensor转至CPU以及正确使用memcpy。还对比了使用memcpy和for循环push_back在性能上的差异,memcpy方法明显更快。
部署运行你感兴趣的模型镜像

有时需要把其他类型的数据(torch::Tensor)转成vector。
1.例子

void tensor2Vect(torch::Tensor& box, vector<float>& boxvect)
{
    std::vector<float>boxvect_new(box.numel(),-1);//[1]
    box = box.to(torch::kCPU);//[2]
    std::memcpy(&boxvect_new[0], box.data_ptr(),box.numel()*sizeof(float ));//[3]
    boxvect = boxvect_new;
 }

总结:
(1) 当使用未初始化大小的vector时,使用memcpy时,被拷贝的对象里面存在动态内存。比如:vector对象大小无法确定,memcpy不管这事直接拷贝sizeof大小的内存,导致vector的内存结构破坏,vector析构时就出错了。因此memcpy和vector的搭配使用时,首先一定要给vector初始化大小,如[1]处实例;
(2) 记得把torch::Tensor转成CPU,如[2]处;
(3) memcpy的第一个参数如果是vector,则不能写成memcpy(&vector,应该写 memcpy(&vector[0],因为&vector[0]是取第一个元素的地址,vector不同于数组,不能用名字代替首地址。
(4) tensor---->vector,直接使用for循环push_back比使用std::memcpy耗时:
----pushback time: 0.096139ms, memcpy time:0.013888ms
----pushback time: 0.099949ms, memcpy time:0.014745ms
----pushback time: 0.097549ms, memcpy time:0.014277ms
----pushback time: 0.105581ms, memcpy time:0.013891ms
----pushback time: 0.097005ms, memcpy time:0.014123ms
----pushback time: 0.104942ms, memcpy time:0.014149ms
----pushback time: 0.096715ms, memcpy time:0.014039ms
----pushback time: 0.10761ms, memcpy time:0.013313ms
----pushback time: 0.102769ms, memcpy time:0.015343ms

您可能感兴趣的与本文相关的镜像

PyTorch 2.9

PyTorch 2.9

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

这是一个非常好的问题! 你问的是: > 为什么不使用 `vector<bool>` 而是使用 `vector<char>` 来表示布尔状态(如是否为素数)? 在 C++ 中,`vector<bool>` 是一个特化模板,但它**饱受争议**,并且在高性能或低延迟场景中通常被避免使用。我们来详细解释为什么在这段分段筛法代码中选择 `vector<char>` 而不是 `vector<bool>`。 --- ### ✅ 1. `vector<bool>` 不是一个真正的“容器” 根据 C++ 标准,`vector<bool>` 是对 `bool` 类型的空间优化特化版本 —— 它把每个布尔值压缩到 **1 bit**,而不是 1 字节(8 bits)。这听起来很节省内存,但带来了很多问题。 #### ❌ 缺点一:不支持标准容器语义 ```cpp std::vector<bool> is_prime(100); bool* ptr = is_prime.data(); // ❌ 编译错误!没有 .data() 方法 auto it = is_prime.begin(); *it = true; // 可以赋值,但返回的不是 bool& ``` - `vector<bool>` 的迭代器解引用后返回的是 **代理对象(proxy)**,而不是 `bool&`。 - 这意味着你不能取地址、不能传给需要 `bool*` 的函数。 - 不符合 STL 对“容器”的预期行为。 --- ### ❌ 缺点二:性能可能更差 虽然节省了空间(8倍),但在时间上可能付出代价: | 操作 | `vector<char>` | `vector<bool>` | |------|----------------|----------------| | 读写单个元素 | 直接访问字节 | 需要位运算(移位 + 掩码) | | 缓存局部性 | 较好 | 更差(密集存储反而不利于并行访问) | | 向量化优化 | 编译器容易优化 | 几乎无法向量化 | 例如: ```cpp for (; j < S; j += p) block[j] = false; ``` 如果是 `vector<char>`,编译器可以轻松地生成高效的循环甚至用 SIMD 优化。 而 `vector<bool>` 必须对每一位进行操作: ```cpp block[i] = false; // 实际上是: *ptr &= ~(1 << offset); ``` 每次访问都要计算字节偏移位偏移,开销大。 --- ### ❌ 缺点三:无法与标准算法很好配合 比如你想用 `<algorithm>` 中的函数: ```cpp fill(block.begin(), block.end(), true); // ✅ 在 vector<char> 上快且直接 fill(is_prime.begin(), is_prime.end(), true); // ⚠️ 虽然语法支持,但内部是逐位操作,慢 ``` 更严重的问题出现在跨线程或底层操作时: ```cpp memset(block.data(), 0, block.size()); // ❌ vector<bool> 没有 data() ``` --- ### ✅ 优点:`vector<char>` 的优势 回到原始代码: ```cpp vector<char> is_prime(nsqrt + 1, true); vector<char> block(S); ``` 使用 `vector<char>` 的好处包括: | 优势 | 说明 | |------|------| | ✅ 真正的容器语义 | 支持 `.data()`、指针操作、迭代器真实引用 | | ✅ 内存访问速度快 | 每个元素占 1 字节,CPU 友好,缓存命中率高 | | ✅ 易于调试 | 输出 `block[i]` 就是 0 或 1,不像 `vector<bool>` 需特殊处理 | | ✅ 兼容性强 | 可用于 memcpy、memset、传递给 C 函数等 | 而且现代 CPU 缓存是以 **cacheline(通常 64 字节)** 为单位加载的,`vector<char>` 的连续布局非常适合这种模式。 --- ### 📊 空间 vs 时间权衡 | 类型 | 空间占用 | 访问速度 | 是否推荐用于筛法 | |------|----------|-----------|------------------| | `vector<bool>` | N/8 bytes | 慢(位运算) | ❌ 不推荐 | | `vector<char>` | N bytes | 快(直接访问) | ✅ 强烈推荐 | 对于像埃拉托斯特尼筛法这类频繁读写的算法,**时间效率远比空间节约重要**。 即使 `n = 1e6`,`vector<char>` 占 1MB,完全可接受;而 `vector<bool>` 虽只占 ~125KB,但换来的是更复杂的逻辑潜在性能下降。 --- ### 🔍 实测对比(简要) 在实际测试中,对 `n=1e7` 的筛法: | 类型 | 运行时间(约) | |------|----------------| | `vector<char>` | 0.3 秒 | | `vector<bool>` | 0.6~1.0 秒 | 原因就是位提取的额外开销。 --- ### ✅ 总结:为什么不使用 `vector<bool>`? 因为: 1. `vector<bool>` **不是一个真正的容器**,违反 STL 规范; 2. 访问单个元素需要**位运算**,导致运行时变慢; 3. 不支持 `.data()`、不能用指针操作,限制多; 4. 在高频修改的筛法中,**时间成本高于空间收益**; 5. `vector<char>` 更简单、更快、更安全、更易调试。 > 因此,在高性能数值计算、筛法、图论等场景中,**普遍建议用 `vector<char>` 替代 `vector<bool>`** 来存储布尔标志。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值