Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在C++;关于CPU和内存_C++_C++11_Unordered Map - Fatal编程技术网

C++ 如何在C++;关于CPU和内存

C++ 如何在C++;关于CPU和内存,c++,c++11,unordered-map,C++,C++11,Unordered Map,我正在迭代一个映射,需要根据未找到元素的条件(可能是任何其他条件)在该映射上添加元素 我的主要问题是,由于要添加大量更新,应用程序占用了整个CPU和所有内存 国家级: class State { int id; int timeStamp; int state; } 状态中的方法: void State::updateStateIfTimeStampIsHigher(const State& state) { if (this->id ==

我正在迭代一个映射,需要根据未找到元素的条件(可能是任何其他条件)在该映射上添加元素

我的主要问题是,由于要添加大量更新,应用程序占用了整个CPU和所有内存

国家级:

class State {

    int id;

    int timeStamp;

    int state;

}
状态中的方法:

void State::updateStateIfTimeStampIsHigher(const State& state) {
    if (this->id == state.getId() && state.getTimeStamp() > this->getTimeStamp()) {
        this->timeStamp = state.getTimeStamp();
        this->state = state.getState();
    }
}
循环代码:

std::map<int, State> data;

const std::map<int, State>& update;

for (auto const& updatePos : update) {
    if (updatePos.first != this->toNodeId) {
        std::map<int, State>::iterator message = data.find(updatePos.first);
        if (message != data.end() && message->first) {
            message->second.updateStateIfTimeStampIsHigher(updatePos.second);
        } else {
            data.insert(std::make_pair(updatePos.first, updatePos.second));
        }
    }
}
std::地图数据;
const std::映射和更新;
用于(自动常量和更新:更新){
if(updatePos.first!=this->toNodeId){
std::map::iterator message=data.find(updatePos.first);
if(message!=data.end()&&message->first){
message->second.updateStateIfTimeStampIsHigher(updatePos.second);
}否则{
data.insert(std::make_pair(updatePos.first,updatePos.second));
}
}
}
查看KCacheGrind数据看起来像data.insert()行占用了大部分时间/内存。我是KCacheGrind的新手,但这条线似乎占到了成本的72%左右


你对如何改进这一点有什么建议吗?

你的问题很笼统,但我认为有一些方法可以让它运行得更快:

  • 使用暗示插入/就位。添加新元素时,将返回其迭代器。假设两个映射以相同的方式排序,您可以知道最后一个映射插入了哪里,因此查找速度应该更快(这里可以使用一些基准测试)
  • 使用
    emplace\u hint
    更快地插入
  • 此处的示例代码:

    std::map<int, long> data;
    
    const std::map<int, long> update;
    auto recent = data.begin();
    
    for (auto const& updatePos : update) {
        if (updateElemNotFound) { 
            recent = data.emplace_hint(recent, updatePos);
        }
    }
    
    std::地图数据;
    const std::地图更新;
    自动最近=data.begin();
    用于(自动常量和更新:更新){
    如果(UpdateLemNotFound){
    最近=数据。安放提示(最近,更新);
    }
    }
    

    另外,如果你想用CPU来交换内存,你可以使用无序的映射(),但第一个点不再重要。

    通过研究对这个问题的评论,我可以找到一个满意的答案。从地图改为无序地图确实有点帮助,但我还是得到了不满意的结果

    我最终使用了谷歌的,它提供了更好的资源利用率,尽管删除条目有一些缺点(我确实这么做)

    代码解决方案如下所示。首先,我包括所需的库:

    #include <sparsehash/sparse_hash_map>
    
    最后,我的循环代码变化很小:

    for (auto const& updatePos : update) {
        if (updatePos.first != this->toNodeId) {
            google::sparse_hash_map<int, State, std::tr1::hash<int>, eqint>::iterator msgIt = data.find(updatePos.first);
            if (msgIt != data.end() && msgIt->first) {
                msgIt->second.updateStateIfTimeStampIsHigher(updatePos.second);
            } else {
                data[updatePos.first] = updatePos.second;
            }
        }
    }
    
    在相同的特定参数下对整个应用程序运行进行更改后的时间为:

    real    0m37,464s
    user    0m37,032s
    sys     0m0,428s
    
    我将其与其他案例和类似结果(从定性角度)一起运行。系统时间和资源使用(CPU和内存)减少,用户时间增加


    总的来说,我对这个折衷方案感到满意,因为我更关心的是资源使用情况而不是执行时间(应用程序是一个模拟器,它无法在非常重的负载下完成并获得结果,现在它可以了)。

    您考虑过
    数据吗?您应该阅读以下内容:1)Francois的建议2)如何更改数据和算法?例如,您是否需要
    int
    作为键?什么是
    状态
    ?它是否足够小,以至于复制构造函数速度很快,或者可以将其更改为小?
    int
    键是否足够密集,可以使用
    std::vector
    而不使用键,并且在未使用的索引处有空白?等等,等等…由于两个贴图具有相同的结构,您可以使用暗示插入,因为您保证在末尾插入。这不会节省分配,而是节省搜索时间。
    update
    map是否必须保持不变?如果您可以将其分解,则可以节省重新分配的费用。您的算法具有
    n log n
    复杂性,而它可以使用与合并算法等效的线性时间来完成。使用emplace_提示并不能提供更好的性能,但将映射更改为无序映射会产生一些性能增益。我仍然需要努力改进。这个解决方案的缺点是我无法使它在Windows上工作。它在Linux上工作。
    for (auto const& updatePos : update) {
        if (updatePos.first != this->toNodeId) {
            google::sparse_hash_map<int, State, std::tr1::hash<int>, eqint>::iterator msgIt = data.find(updatePos.first);
            if (msgIt != data.end() && msgIt->first) {
                msgIt->second.updateStateIfTimeStampIsHigher(updatePos.second);
            } else {
                data[updatePos.first] = updatePos.second;
            }
        }
    }
    
    real    0m28,592s
    user    0m27,912s
    sys     0m0,676s
    
    real    0m37,464s
    user    0m37,032s
    sys     0m0,428s