c – 线程安全内存池

c – 线程安全内存池,第1张

概述我的应用程序目前是高性能关键的,每帧需要3-5万个对象.最初,为了让球滚动,我新的一切,并让应用程序工作和测试我的算法.该应用程序是多线程的. 一旦我对表演感到满意,我开始为我的对象创建一个内存管理器.明显的原因是记忆碎片和浪费.由于内存碎片,应用程序在崩溃之前无法继续超过几帧.我检查了内存泄漏,知道应用程序是无泄漏的. 所以我开始使用TBB的concurrent_queue创建一个简单的内存管理 我的应用程序目前是高性能关键的,每帧需要3-5万个对象.最初,为了让球滚动,我新的一切,并让应用程序工作和测试我的算法.该应用程序是多线程的.

一旦我对表演感到满意,我开始为我的对象创建一个内存管理器.明显的原因是记忆碎片和浪费.由于内存碎片,应用程序在崩溃之前无法继续超过几帧.我检查了内存泄漏,知道应用程序是无泄漏的.

所以我开始使用TBB的concurrent_queue创建一个简单的内存管理器.队列存储应用程序允许使用的最大元素集.需要新元素的类从队列中d出元素.根据英特尔的文档,try_pop方法是无锁的.就内存消耗而言(尽管仍然存在内存碎片,但并不像以前那样),这一点很好.我现在面临的问题是,根据我自己的简单分析器,应用程序的性能已经减慢了大约4倍(我无法访问商业分析器,或者知道任何可以在实时应用中工作的任何建议将不胜感激).

我的问题是,是否有可扩展的线程安全内存池.游泳池的必备功能是快速回收元素并使其可用.如果没有,任何提示/技巧表现明智?

编辑:我以为我会解释一下这个问题.我可以轻松地初始化n个数组,其中n是线程数,并开始使用每个线程的数组中的对象.对于某些情况,这将很好地工作.在我的情况下,我正在回收元素(可能是每个框架),并且它们可以在数组中的任何点被回收;即它可能来自数组的elementArray [0]或elementArray [10]或elementArray [1000]部分.现在我将有一个零碎的数组元素组成的元素可以使用和元素的使用:(

解决方法 正如在评论中所说,不要得到一个线程安全的内存分配器,每线程分配一个内存.

正如您在更新中所暗示的,您需要有效地管理免费/有效的使用.这是一个非常简单的问题,给定一个恒定的类型并不是并发的.

例如(从我的头顶部,未经测试):

template<typename T>class ThreadStorage{    std::vector<T> m_obJs;    std::vector<size_t> m_avail;public:    explicit ThreadStorage(size_t count) : m_obJs(count,T()) {        m_avail.reserve(count);        for (size_t i = 0; i < count; ++i) m_avail.push_back(i);    }    T* alloc() {        T* retval = &m_obJs[0] + m_avail.back();        m_avail.pop_back();        return retval;    }    voID free(T* p) {        *p = T(); // Assuming this is enough destruction.        m_avail.push_back(p - &m_obJs[0]);    }};

然后,对于每个线程,都有一个ThreadStorage实例,并根据需要调用alloc()和free().

您可以添加智能指针来管理您的自由(),如果昂贵,您可以优化构造函数/析构函数调用.

你也可以看看boost :: pool.

更新:

跟踪已经被使用的东西,以便可以在第二次通过处理的新要求似乎对我来说有些不清楚.我想你的意思是当一个对象上的主处理完成时,你不需要释放它,但是请继续参考它进行第二阶段的处理.一些对象,您将被释放回池,不用于第二阶段处理.

我假设你想在同一个线程中这样做.

作为第一遍,您可以向ThreadStorage添加一个这样的方法,当您想对所有未发布的T实例进行处理时调用它.不需要额外的书本保留.

voID do_processing(boost::function<voID (T* p)> const& f) {    std::sort(m_avail.begin(),m_avail.end());    size_t o = 0;    for (size_t i = 0; i != m_avail.size(); ++i) {        if (o < m_avail[i]) {            do {                f(&m_obJs[o]);            } while (++o < m_avail[i]);            ++o;        } else of (o == m_avail[i])            ++o;    }    for (; o < m_obJs.size(); ++o) f(&m_obJs[o]);}

假设没有其他线程正在使用ThreadStorage实例,这是合理的,因为它是线程本地的设计.再次,我的头顶,未经测试.

总结

以上是内存溢出为你收集整理的c – 线程安全内存池全部内容,希望文章能够帮你解决c – 线程安全内存池所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1248320.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-07
下一篇2022-06-07

发表评论

登录后才能评论

评论列表(0条)

    保存