gpt4 book ai didi

c++ - 线程安全内存池

转载 作者:IT老高 更新时间:2023-10-28 23:00:47 25 4
gpt4 key购买 nike

我的应用程序目前对性能至关重要,每帧请求 3-5 百万个对象。最初,为了让一切顺利进行,我new'd 一切,让应用程序工作并测试我的算法。该应用程序是多线程的。

一旦我对性能感到满意,我就开始为我的对象创建一个内存管理器。显而易见的原因是内存碎片和浪费。由于内存碎片,应用程序在崩溃之前无法继续运行超过几帧。我检查了内存泄漏并且知道应用程序没有泄漏。

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

我的问题是,是否存在可扩展的线程安全内存池。池的一个 must-have 功能是快速回收元素并使其可用。如果没有,任何提示/技巧性能明智?

编辑:我想我会多解释一下这个问题。我可以轻松地初始化 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()。

您可以添加智能指针来为您管理调用 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++ - 线程安全内存池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5737344/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com