提升多索引容器,如何快速插入延迟索引?

时间:2015-02-15 02:31:50

标签: c++ performance boost

我在MultiIndexContainer下面使用

typedef multi_index_container<PositionSummary*,
        indexed_by<
                ordered_unique<
                        composite_key<PositionSummary, const_mem_fun<PositionSummary, int, &PositionSummary::positiondate>,
                                const_mem_fun<PositionSummary, const std::string&, &PositionSummary::accountid>,
                                const_mem_fun<PositionSummary, const std::string&, &PositionSummary::instid> > >,
                ordered_unique<
                        composite_key<PositionSummary, const_mem_fun<PositionSummary, int, &PositionSummary::positiondate>,
                                const_mem_fun<PositionSummary, const std::string&, &PositionSummary::instid>,
                                const_mem_fun<PositionSummary, const std::string&, &PositionSummary::accountid> > > 
                    > > PositionSummaryContainer;

我插入10000个内存* 36个帐户* 100天= 3600万个记录

//Begin testing of the multiIndexContainter
std::cout << "Begin inserting data from array into the multiIndexContainter" << std::endl;
timer.reset();
timer.begin();
for (int i = 0; i < numOfDays_; i++)
{
    for (int j = 0; j < accountSize_; j++)
    {
        for (int k = 0; k < instSize_; k++)
        {
            PositionSummary* ps = psArray_[(i * accountSize_ + j) * instSize_ + k];
            uniqueIndex.insert(ps);
        }
    }

}

printMemoryUsage();
timer.end();
std::cout << "Time take is " << timer.getInterval() << std::endl;

我发现插入速度有点慢,大约每秒20K +记录......无论如何都要提高插入速度吗? 我的数据在Oracle中,正确编制索引,因此不存在数据结构损坏的危险。我知道在oracle中你可以先加载然后构建索引以节省时间,如果有方法可以用MultiIndexContainer做同样的事情吗? 顺便说一句,并行查询速度是相当令人满意的,查询4 cpu(8kernal)机器上的所有36 m记录只需2.8秒,代码如下

#pragma omp parallel for collapse(2)
    for (int i = 0; i < numOfDays_; i++)
    {

        for (int j = 0; j < accountSize_; j++)
        {
            const int& date = dates_[i];
            const std::string& accountID = accountIDs_[j];
            for (int k = 0; k < instSize_; k++)
            {
                const std::string& instID = instIDs_[i];
                PositionSummaryContainer::iterator it = uniqueIndex.find(boost::make_tuple(date, accountID, instID));
                if (it != uniqueIndex.end())
                {
#pragma omp atomic
                    sum2 += (*it)->marketvalue();
                }
            }
            //std::cout << "accountID: " << accountID << std::endl;
        }

    }

2 个答案:

答案 0 :(得分:1)

啊,我想我找到了钥匙。这很简单。

psContainer_.insert(&psArray_[0], &psArray_[accountSize_ * instSize_ * numOfDays_]);

现在插入速度从53秒减少到5.29秒。改善十倍。我认为提升作者知道他们使用这种方式进行了一些批量插入,只是我没有注意到。

Boost是一个很棒的lib,但文档并不是那么彻底。

答案 1 :(得分:0)

据我所知,这不是一个功能。
(的 Is using a map where value is std::shared_ptr a good design choice for having multi-indexed lists of classes?

  • 我必须说有两个等价的复合索引看起来像代码味道。在我看来,你应该有更少或更多的独立指数。
  • 通过指针存储PositionSummary也可能是一种气味;它很容易杀死记忆地点
  • 显示使用模式,使用多索引容器是过度的。你可以(应该)只使用例如boost::flat_set(基本上是您的使用示例中使用的主索引的vector<PositionSummary>顺序)。见

  • 您可以在上述任何场景中使用持久性容器(使用Boost Interprocess managed_shared_memory / managed_mapped_file段分配器。请参阅我的许多答案中的示例)。这将完全/大部分消除加载时间

  • 您可以使用#pragma omp parallel for reduction(+:sum2),这会大大减少sum2变量上的缓存失效

  • 看起来非常像你在两个正交的维度(日期/帐户)上即时整合度量。这应该提醒您“数据透视表”,从而提醒您OLAP(多维数据集)报告数据库。

    而不是将批量数据“导出”到您的专有C ++应用程序中,您可以将其导出到OLAP分析/报告引擎(Business Objects(ROLAP),MS Analysis Server(OLAP),OracleEssbase¹)并使用其出色的优化报告和(预)合并功能。

    有一种专用的查询语言: MDX for OLAP databases ,您可以使用它,就像您使用的那样来自C ++的OCI


¹前Arbor Essbase - &gt; Hyperion Essbase - &gt; Oracle Essbase