Parallel processing ';新';和';删除';没有“英特尔线程构建块”可扩展\u malloc/free那样可扩展

Parallel processing ';新';和';删除';没有“英特尔线程构建块”可扩展\u malloc/free那样可扩展,parallel-processing,Parallel Processing,明确地说,这不是tbb图书馆的广告。只是最近我发现了一些让我很惊讶的东西 我用谷歌搜索了一下堆争用。而且似乎在Glibc2.3之后。”“new”和“delete”已得到改进,可以很好地支持多处理器。我的glibc是2.5。下面是非常简单的代码 tbb::tick_count t1 = tbb::tick_count::now(); for (size_t i = 0; i < 100000; ++i) { char * str = new char [10

明确地说,这不是tbb图书馆的广告。只是最近我发现了一些让我很惊讶的东西

我用谷歌搜索了一下堆争用。而且似乎在Glibc2.3之后。”“new”和“delete”已得到改进,可以很好地支持多处理器。我的glibc是2.5。下面是非常简单的代码

tbb::tick_count t1 = tbb::tick_count::now();

    for (size_t i = 0; i < 100000; ++i)
    {
        char * str = new char [100];
        delete str;
    }
tbb::tick_count t2 = tbb::tick_count::now();
std::cout << "process time = " << (t2 - t1).seconds() << std::endl;
tbb::tick_count t1=tbb::tick_count::now();
用于(尺寸i=0;i<100000;++i)
{
char*str=新字符[100];
删除str;
}
tbb::tick_count t2=tbb::tick_count::now();

这根本不是一个谜。众所周知,多线程应用程序中的内存分配会受到线程阻塞时间增加的影响(特别是在Linux上处于内核任务不间断状态的休眠线程)。从堆中分配内存可能很快成为瓶颈,因为标准分配器通过序列化请求来处理来自多个线程的多个分配请求。这些是导致性能下降的主要原因。当然,这反过来又导致了高效分配器的实现。您引用了TBB,但还有其他免费提供的替代方案

例如,请参阅库,正如他的作者所说,“对于使用动态内存分配的多线程应用程序,与SMP平台上的标准分配器相比,该库在性能方面提供了大约10倍的优势”


另一个选择是。

非常感谢您的评论,您能告诉我在哪里可以找到详细解释这一点的文章吗?但是仍然有一个神秘的部分,那就是“如果我在开始运行算法之前在一个紧密的循环中调用‘new’和‘delete’,那么‘new’和‘delete’的开销就消失了。”对此有什么解释吗?我阅读了ThreadAlloc库的文档,对我来说,神秘的一点是,保持互斥的原因是多线程运行缓慢。但我真的怀疑这一点,因为如果互斥是原因,那么在多处理器平台上的多线程中运行“for(size_t I=0;I<10000000;++I)char*p=new char[100];delete p;”这样的代码肯定会更好,但实际上更快。对我来说,另一个难题是,无论如何,它应该是一样快的,为什么它会更快。顺便说一句,我测试了囤积,我真的没有做tbb的广告。但是从结果来看,tbb的速度大约是CADGE的两到四倍。下面是几篇文章,让您开始:如果在算法之前运行示例代码,您没有看到开销的最可能原因是,开始时产生的开销通过随后运行算法进行补偿。相反,如果先运行算法,然后运行示例代码,那么一旦算法完成,就无法恢复任何内容。在实践中,该算法可能在某种意义上掩盖了开销。