最佳实践:函数(C ++)中大时间缓冲区的频繁使用

问题描述 投票:1回答:2

我经常遇到这样的问题:我的函数需要一些内部计算的内存。该函数将被高频率调用。可能是因为内存量太大而无法放入堆栈。因此,我必须分配和取消分配内存。但是,我非常担心这种频繁,不必要的分配/释放所引起的开销。

我目前看到以下选项:

  1. 每次分配/取消分配
  2. 使用静态变量将内存与共享指针结合使用,以确保安全销毁分配的内存
  3. 使用全局(或文件范围)内存来始终保留分配的内存。
  4. 将函数封装在Class内,并添加一个用于保存分配的内存的成员变量(这里我最关心的是

关于方法3-4:我最担心的是,实际上该存储器中的值仅在该函数内有效,并且仅应在该函数中使用。但是,实际上,变量的范围更大,并且很容易出现变量的误用或意外使用。必须明确指出,不打算在函数之外使用这些变量。我现在最喜欢的是选项2。在这种情况下,我很高兴听到您对最佳实践方法的意见。

认真修改的问题:想象一下,我们现在有了一个成员方法,而不是一个独立的函数。在这里,我最喜欢的方法2不再起作用,因为该类的所有实例将共享同一计算缓冲区。因此,我认为只有两种选择:1.每次分配/解除分配2.为每个插件使用成员变量来分配内存。

关于方法2,我再次感到不信任:同一类中的所有函数都可以访问成员变量,尽管预期的范围应该仅用于此单个成员函数中的时间计算。

也许此变量的一些命名约定以及注释可能会有所帮助:E.g

...
private:
/** this variable is only intended to be used temporarily within fct1 */
std::shared_ptr<std::array<double, 10000>> tmpBuffer;
...
c++ memory-management
2个回答
0
投票

您在“稍作修改”问题中的做法似乎是合理的。如果您有一个函数重复处理某些数据,但又在某些其他范围内以有限的方式使用了这些函数,但又不希望整个程序访问,则可能暗示该数据和这些函数应捆绑在一起同一类中的成员和方法。一旦定义了该类,就可以通过范围界定,std::shared_ptr或类似方法等常规方法更简单地处理其实例的生存期。

那时,除非您有进一步的具体证据表明该类的作用域和布局正在引起问题,否则应该明智地相信编译器,CPU缓存等正在为您做出不错的选择,直到对数据进行剖析证明是相反的为止。 。


0
投票

假设您具有要使用大的临时缓冲区F的函数B

  1. 如果要频繁调用B,则您不想在每次调用F时分配和取消分配F

  2. 我不确定您在选项#2中的含义。如果将B声明为静态,则不要/不应将其放入shared_ptr中。静态变量具有程序生存期,不能/不应通过智能指针进行管理。

  3. 从性能的角度来看,使用全局B与使用静态B本质上是相同的,除了使用全局其他功能之外,其他功能也可以访问B,这似乎不是您想要的。

  4. 您可以将B封装在类C内,构造实例S,并将S的引用作为参数传递给F。除非您也将B传递给其他功能,否则其他功能将无法访问S

我认为,在上述4个选项中,出于性能原因,您不想执行#1,#2在可见性方面要比#3更好,而#4似乎是最灵活的。

通过在#4的B的访问器中使用原子操作,您还可以允许多个线程在共享对B的访问的同时调用该函数。或者,您可以在不应共享同一缓冲区的线程中简单使用C的不同实例。 F是否是类成员方法的静态函数也无关紧要;行为是相同的。

缺点是F现在需要一个额外的参数(C& s),其寿命需要由程序在F之外进行管理。但这本质上就是您想要的-性能优化。

© www.soinside.com 2019 - 2024. All rights reserved.