如何优化C++键值程序以获得更快的运行时间
How do I Optimize my C++ key-value program to have a faster runtime?
这是一个可以编辑的程序,据我所知,代码是正确的,只是太慢了。老实说,我在这里迷路了,我知道我的for循环可能是让我这么慢的原因,也许使用迭代器?
// <algorithm>, <list>, <vector>
// YOU CAN CHANGE/EDIT ANY CODE IN THIS FILE AS LONG AS SEMANTICS IS UNCHANGED
#include <algorithm>
#include <list>
#include <vector>
class key_value_sequences {
private:
std::list<std::vector<int>> seq;
std::vector<std::vector<int>> keyref;
public:
// YOU SHOULD USE C++ CONTAINERS TO AVOID RAW POINTERS
// IF YOU DECIDE TO USE POINTERS, MAKE SURE THAT YOU MANAGE MEMORY PROPERLY
// IMPLEMENT ME: SHOULD RETURN SIZE OF A SEQUENCE FOR GIVEN KEY
// IF NO SEQUENCE EXISTS FOR A GIVEN KEY RETURN 0
int size(int key) const;
// IMPLEMENT ME: SHOULD RETURN POINTER TO A SEQUENCE FOR GIVEN KEY
// IF NO SEQUENCE EXISTS FOR A GIVEN KEY RETURN nullptr
const int* data(int key) const;
// IMPLEMENT ME: INSERT VALUE INTO A SEQUENCE IDENTIFIED BY GIVEN KEY
void insert(int key, int value);
}; // class key_value_sequences
int key_value_sequences::size(int key) const {
//checks if the key is invalid or the count vector is empty.
if(key<0 || keyref[key].empty()) return 0;
// sub tract 1 because the first element is the key to access the count
return keyref[key].size() -1;
}
const int* key_value_sequences::data(int key) const {
//checks if key index or ref vector is invalid
if(key<0 || keyref.size() < static_cast<unsigned int>(key+1)) {
return nullptr;
}
// ->at(1) accesses the count (skipping the key) with a pointer
return &keyref[key].at(1);
}
void key_value_sequences::insert(int key, int value) {
//checks if key is valid and if the count vector needs to be resized
if(key>=0 && keyref.size() < static_cast<unsigned int>(key+1)) {
keyref.resize(key+1);
std::vector<int> val;
seq.push_back(val);
seq.back().push_back(key);
seq.back().push_back(value);
keyref[key] = seq.back();
}
//the index is already valid
else if(key >=0) keyref[key].push_back(value);
}
#endif // A2_HPP
这是a2.cpp,这只是测试a2.hpp的功能,此代码不能更改
// DO NOT EDIT THIS FILE !!!
// YOUR CODE MUST BE CONTAINED IN a2.hpp ONLY
#include <iostream>
#include "a2.hpp"
int main(int argc, char* argv[]) {
key_value_sequences A;
{
key_value_sequences T;
// k will be our key
for (int k = 0; k < 10; ++k) { //the actual tests will have way more than 10 sequences.
// v is our value
// here we are creating 10 sequences:
// key = 0, sequence = (0)
// key = 1, sequence = (0 1)
// key = 2, sequence = (0 1 2)
// ...
// key = 9, sequence = (0 1 2 3 4 5 6 7 8 9)
for (int v = 0; v < k + 1; ++v) T.insert(k, v);
}
T = T;
key_value_sequences V = T;
A = V;
}
std::vector<int> ref;
if (A.size(-1) != 0) {
std::cout << "fail" << std::endl;
return -1;
}
for (int k = 0; k < 10; ++k) {
if (A.size(k) != k + 1) {
std::cout << "fail";
return -1;
} else {
ref.clear();
for (int v = 0; v < k + 1; ++v) ref.push_back(v);
if (!std::equal(ref.begin(), ref.end(), A.data(k))) {
std::cout << "fail 3 " << A.data(k) << " " << ref[k];
return -1;
}
}
}
std::cout << "pass" << std::endl;
return 0;
} // main
如果有人能帮助我提高代码效率,我将非常感激,谢谢。
首先,我不相信您的代码是正确的。在插入中,若它们的关键帧有效,则创建一个新的矢量并将其插入序列中。听起来不对,因为只有当你有了新钥匙时才会发生这种情况,但如果你的测试通过了,那可能没问题。
性能方面:
- 避免std::list。链表在当今的硬件上有着糟糕的性能,因为它们破坏了流水线、缓存和预取。始终使用std::vector。如果有效负载非常大并且您担心拷贝,请使用
std::vector<std::unique_ptr<T>>
- 尽量避免复制矢量。在您的代码中,您有
keyref[key] = seq.back()
,它复制向量,但应该没问题,因为它只是一个元素
否则不会出现明显的性能问题。试着对你的程序进行基准测试和评测,看看慢的部分在哪里。通常有一两个地方需要进行优化并获得出色的性能。如果速度仍然太慢,请问另一个问题,将结果发布在哪里,以便我们更好地了解问题。
我会和Sorin一起说,如果可以避免,就不要使用std::list。
所以你用key
作为直接索引,它在哪里说它不是负的?它在哪里说它不到1亿?
void key_value_sequences::insert(int key, int value) {
//checks if key is valid and if the count vector needs to be resized
if(key>=0 && keyref.size() < static_cast<unsigned int>(key+1)) {
keyref.resize(key+1); // could be large
std::vector<int> val; // don't need this temporary.
seq.push_back(val); // seq is useless?
seq.back().push_back(key);
seq.back().push_back(value);
keyref[key] = seq.back(); // we now have 100000000-1 empty indexes
}
//the index is already valid
else if(key >=0) keyref[key].push_back(value);
}
能做得更快吗?取决于您的key
范围是的,它可以。您将需要实现一个flat_map或hash_map。
用于flat_map版本的C++11概念代码。
// effectively a binary search
auto key_value_sequences::find_it(int key) { // type should be iterator
return std::lower_bound(keyref.begin(), keyref.end(), [key](const auto& check){
return check[0] < key; // key is 0-element
});
}
void key_value_sequences::insert(int key, int value) {
auto found = find_it(key);
// at the end or not found
if (found == keyref.end() || found->front() != key) {
found = keyref.emplace(found, key); // add entry
}
found->emplace_back(value); // update entry, whether new or old.
}
const int* key_value_sequences::data(int key) const {
//checks if key index or ref vector is invalid
auto found = find_it(key);
if (found == keyref.end())
return nullptr;
// ->at(1) accesses the count (skipping the key) with a pointer
return found->at(1);
}
(希望我说得对…(
相关文章:
- 用时钟测量程序的运行时间
- 我的 c++ 应用程序中的运行时间从 0 增加到 60 太快了(例如一毫秒或一微秒)
- 如何执行用 C++ 编写的程序的运行时间?
- 如何优化C++键值程序以获得更快的运行时间
- 同一程序的运行时间差异很大,有时达到1000+us
- 测量 OpenCL 应用程序的运行时间
- 如何修复数据库连接的C 程序运行时间错误(0xc0000005)
- 如何在以下C程序中计算运行时间内存和最大数据存储器使用情况
- 使用Clock()函数测量程序的运行时间
- 对于长时间运行的程序,STL 内存管理是否"reliable"?
- 测量 C++ 多线程程序中的运行时间
- 运行时间错误:程序跳过提示,以获取第二名和第三个名称
- 将一个大文件加载到内存中并在程序的所有运行时间内保持它是错误的
- 如果你以root用户身份运行这个C++程序,为什么它要花这么长时间才能完成
- 为什么我的C++程序使用的系统时间比运行时间多
- 与linux相比,cygwin中的c++程序运行时间较长
- 如何分析程序运行时间
- 计算并行程序的运行时间和cpu时间
- 如何为长时间运行的程序执行文件输出
- 使用 Unix 程序时间计算每次迭代的程序运行时间