最佳做法:在函数中频繁使用大时态缓冲区 (C++)
Best Practice: Frequent usage of big temporal buffer within function (C++)
我经常遇到一个问题,我得到一个函数,它需要更大的内存来进行一些内部计算。 该函数将以高频率调用。 可能是内存量太大而无法放入堆栈。因此,我必须分配和释放内存。 但是,我非常担心这种频繁的、不必要的分配/取消分配造成的开销。
我目前看到以下选项:
- 每次分配/取消分配
- 使用静态变量将内存与共享指针结合使用,以确保安全销毁分配的内存
- 使用全局(或文件范围(内存来保持为整个时间分配的内存。
- 将函数封装在类中并添加一个保存分配内存的成员变量(这里我最关心的是
关于方法3-4:我最关心的是,实际上这个内存中的值只在这个函数中有效,应该只在那里使用。但是,实际上变量的范围更大,并且很容易误用或意外使用变量。必须明确的是,它不打算在函数之外使用这些变量。 我现在最喜欢的是选项 2。 我很高兴听到您对本案最佳实践方法的意见。
略微修改的问题: 想象一下,我们现在有一个成员方法,而不是一个独立的函数。 在这里,我最喜欢的方法 2 将不再起作用,因为该类的所有实例将共享相同的计算缓冲区。因此,我认为只有两种选择: 1. 每次分配/取消分配 2. 为每个插件使用一个成员变量来保持内存分配。
关于方法 2,我再次得到了一些不信任:成员变量可以被同一类中的所有函数访问,尽管预期范围应该仅用于这个单个成员函数中的临时计算。
也许这个变量的一些命名约定以及注释会有所帮助: 例如
...
private:
/** this variable is only intended to be used temporarily within fct1 */
std::shared_ptr<std::array<double, 10000>> tmpBuffer;
...
您在"略有修改"问题中的方法似乎是合理的。 如果你有一个函数重复操作某些数据片段,这些数据在其他一些作用域中以有限的方式使用,但不是整个程序可以访问的,这可能是一个提示,表明数据和这些函数应该作为成员和方法绑定在一起在同一类中。 定义该类后,可以通过常规方法(如范围、std::shared_ptr
或类似方法(更简单地处理其实例的生存期。
此时,除非您有进一步的具体证据表明该类的范围和布局导致了问题,否则明智的做法是相信编译器、CPU 缓存等正在为您做出正确的选择,直到分析数据证明并非如此。
假设您有一个函数F
想要使用大型临时缓冲区B
。
-
如果调用频率较高
F
则不希望每次调用F
时都分配和取消分配B
。 -
我不确定您在选项 #2 中的意思。如果
B
被声明为静态,那么您不会/不应该将其放入shared_ptr
中。静态变量具有程序生存期,不能/不应该由智能指针管理。 -
从性能的角度来看,使用全局
B
本质上与使用静态B
相同,除了全局其他函数也可以访问B
,这似乎并不想要。 -
您可以将
B
封装在类C
中,构造一个实例S
并将S
的引用作为参数传递给F
。其他函数将无法访问B
,除非您也S
传递给它们。
在我看来,在上述 4 个选项中,出于性能原因,您不想做 #1,#2 比 #3 更好,因为可见性更窄,#4 似乎是最灵活的。
通过在 #4 中B
的访问器中使用原子操作,您还可以允许多个线程同时调用该函数,同时共享对B
的访问。或者,您可以简单地在不应共享同一缓冲区的线程中使用不同的C
实例。F
是否是类成员方法的静态函数也无关紧要;行为是相同的。
缺点是F
现在需要一个额外的参数(C& s
(,其生存期需要在程序F
之外进行管理。但这本质上是你想要的 - 用于性能优化。
- C++字符*缓冲区的大小
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- ostream过载时的缓冲区冲洗
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- Xaudio2在更改缓冲区或循环时弹出声音
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 如何在cpp.中使用协议缓冲区存储大缓冲区/数组(char/int)
- 多线程双缓冲区
- Android P-9.0.0_r53 Logcat主缓冲区超出定义大小
- 套接字读取后,我在缓冲区中看到意外输入
- std::带有自定义缓冲区的 iostream 不允许我写入
- 从返回的顶点缓冲区查询顶点结构
- Vulkan 中的动态顶点缓冲区格式设置
- OpenGL 16 位模板缓冲区?
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 在 openGL 中多次绑定缓冲区
- struct.error:解压缩 C++ 结构时,解包需要 288 字节的缓冲区
- 为什么缓冲区的内容在读取空 rdbuf 时被删除?