c++ - std::vector 在加载/清除大量数据时变得越来越慢

标签 c++ arrays windows memory vector

问题

我有一个非常复杂的图像处理应用程序,其中一个子模块需要将巨大的二进制位图加载到内存中。实际上多达 96 GB(即 888 888 x 888 888 像素图像)。磁盘是 2xSSD raid0,读/写速度约为 1 GB/s。它将图像加载到一个 vector (每个元素代表位图中的一行)到带有字节的 vector (每个元素代表 8 个像素)的智能指针。这里奇怪的问题是vector重复加载和清空后(我看到内存确实是填满清空,没有内存泄漏),每次迭代的时间好像越来越长。专门清理内存需要很长时间。

测试

我做了一些简单的测试应用程序来测试这个孤立的和从不同角度。 用原始指针替换智能指针给出了同样的奇怪行为。 然后我尝试使用 native 数组而不是 vector ,这就成功了。在加载/清除 24 GB 的 100 次迭代后,使用 vector 时时间急剧增加,而数组实现在时间上是稳定的。下面是用 24 GB 垃圾填充内存而不是加载实际图像的测试应用程序,结果相同。测试在配备 128 GB RAM 的 Windows 10 Pro 上完成,并使用 Visual Studio 2013 Update 5 构建。

此函数使用 vector 进行加载/清除:

void SimpleLoadAndClear_Vector(int width, int height) {
    time_t start_time, end_time;

    // Load memory
    time(&start_time);
    cout << "Loading image into memory...";
    auto width_bytes = width / 8;
    auto image = new vector<vector<unsigned char>*>(height);
    for (auto y = 0; y < height; y++) {
        (*image)[y] = new vector<unsigned char>(width_bytes);
        auto row_ptr = (*image)[y];
        for (auto b = 0; b < width_bytes; b++) {
            (*row_ptr)[b] = 0xFF;
        }
    }
    cout << "DONE: ";
    time(&end_time);
    auto mem_load = (int)difftime(end_time, start_time);
    cout << to_string(mem_load) << " sec" << endl;

    // Clear memory
    time(&start_time);
    cout << "Clearing memory...";
    for (auto y = 0; y < height; y++) {
        delete (*image)[y];
    }
    delete image;
    cout << "DONE: ";
    time(&end_time);
    auto mem_clear = (int)difftime(end_time, start_time);
    cout << to_string(mem_clear) + " sec" << endl;
}

此函数使用数组来加载清除:

void SimpleLoadAndClear_Array(int width, int height) {
    time_t start_time, end_time;

    // Load memory
    time(&start_time);
    cout << "Loading image into memory...";

    auto width_bytes = width / 8;
    auto image = new unsigned char*[height];
    for (auto y = 0; y < height; y++) {
        image[y] = new unsigned char[width_bytes];
        auto row_ptr = image[y];
        for (auto b = 0; b < width_bytes; b++) {
            row_ptr[b] = 0xFF;
        }
    }
    cout << "DONE: ";
    time(&end_time);
    auto mem_load = (int)difftime(end_time, start_time);
    cout << to_string(mem_load) << " sec" << endl;

    // Clear memory
    time(&start_time);
    cout << "Clearing memory...";

    for (auto y = 0; y < height; y++) {
        delete[] image[y];
    }
    delete[] image;
    cout << "DONE: ";
    time(&end_time);
    auto mem_clear = (int)difftime(end_time, start_time);
    cout << to_string(mem_clear) + " sec" << endl;
}

这是调用上述加载/清除函数的主要函数:

void main()
{
    auto width = 455960;
    auto height = 453994;
    auto i_max = 50;
    for (auto i = 0; i < i_max; i++){
        SimpleLoadAndClear_Vector(width, height);
    }
}

vector 版本的测试输出在 50 次迭代后如下所示(显然加载/清除时间越来越多):

Loading image into memory...DONE: 19 sec
Clearing memory...DONE: 24 sec
Loading image into memory...DONE: 40 sec
Clearing memory...DONE: 20 sec
Loading image into memory...DONE: 27 sec
Clearing memory...DONE: 39 sec
Loading image into memory...DONE: 35 sec
Clearing memory...DONE: 24 sec
Loading image into memory...DONE: 27 sec
Clearing memory...DONE: 34 sec
Loading image into memory...DONE: 33 sec
Clearing memory...DONE: 29 sec
Loading image into memory...DONE: 27 sec
Clearing memory...DONE: 35 sec
Loading image into memory...DONE: 32 sec
Clearing memory...DONE: 33 sec
Loading image into memory...DONE: 28 sec
Clearing memory...DONE: 37 sec
Loading image into memory...DONE: 31 sec
Clearing memory...DONE: 35 sec
Loading image into memory...DONE: 30 sec
Clearing memory...DONE: 38 sec
Loading image into memory...DONE: 31 sec
Clearing memory...DONE: 38 sec
Loading image into memory...DONE: 31 sec
Clearing memory...DONE: 41 sec
Loading image into memory...DONE: 32 sec
Clearing memory...DONE: 40 sec
Loading image into memory...DONE: 33 sec
Clearing memory...DONE: 42 sec
Loading image into memory...DONE: 35 sec
Clearing memory...DONE: 43 sec
Loading image into memory...DONE: 34 sec
Clearing memory...DONE: 46 sec
Loading image into memory...DONE: 36 sec
Clearing memory...DONE: 47 sec
Loading image into memory...DONE: 35 sec
Clearing memory...DONE: 49 sec
Loading image into memory...DONE: 37 sec
Clearing memory...DONE: 50 sec
Loading image into memory...DONE: 37 sec
Clearing memory...DONE: 51 sec
Loading image into memory...DONE: 39 sec
Clearing memory...DONE: 51 sec
Loading image into memory...DONE: 39 sec
Clearing memory...DONE: 53 sec
Loading image into memory...DONE: 40 sec
Clearing memory...DONE: 52 sec
Loading image into memory...DONE: 40 sec
Clearing memory...DONE: 55 sec
Loading image into memory...DONE: 41 sec
Clearing memory...DONE: 56 sec
Loading image into memory...DONE: 41 sec
Clearing memory...DONE: 59 sec
Loading image into memory...DONE: 42 sec
Clearing memory...DONE: 59 sec
Loading image into memory...DONE: 42 sec
Clearing memory...DONE: 60 sec
Loading image into memory...DONE: 44 sec
Clearing memory...DONE: 60 sec
Loading image into memory...DONE: 44 sec
Clearing memory...DONE: 63 sec
Loading image into memory...DONE: 44 sec
Clearing memory...DONE: 63 sec
Loading image into memory...DONE: 45 sec
Clearing memory...DONE: 64 sec
Loading image into memory...DONE: 46 sec
Clearing memory...DONE: 65 sec
Loading image into memory...DONE: 45 sec
Clearing memory...DONE: 67 sec
Loading image into memory...DONE: 47 sec
Clearing memory...DONE: 69 sec
Loading image into memory...DONE: 47 sec
Clearing memory...DONE: 70 sec
Loading image into memory...DONE: 48 sec
Clearing memory...DONE: 72 sec
Loading image into memory...DONE: 48 sec
Clearing memory...DONE: 74 sec
Loading image into memory...DONE: 49 sec
Clearing memory...DONE: 74 sec
Loading image into memory...DONE: 50 sec
Clearing memory...DONE: 74 sec
Loading image into memory...DONE: 50 sec
Clearing memory...DONE: 76 sec
Loading image into memory...DONE: 51 sec
Clearing memory...DONE: 78 sec
Loading image into memory...DONE: 53 sec
Clearing memory...DONE: 78 sec
Loading image into memory...DONE: 53 sec
Clearing memory...DONE: 80 sec
Loading image into memory...DONE: 54 sec
Clearing memory...DONE: 80 sec
Loading image into memory...DONE: 54 sec
Clearing memory...DONE: 82 sec
Loading image into memory...DONE: 55 sec
Clearing memory...DONE: 91 sec
Loading image into memory...DONE: 56 sec
Clearing memory...DONE: 84 sec
Loading image into memory...DONE: 56 sec
Clearing memory...DONE: 88 sec

array 版本的测试输出在 50 次迭代后如下所示(显然加载/清除时间稳定并且不会越来越多):

Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 17 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 17 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 17 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 25 sec
Loading image into memory...DONE: 27 sec
Clearing memory...DONE: 17 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 17 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 17 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 17 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 25 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 25 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 25 sec
Clearing memory...DONE: 19 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 25 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 25 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 25 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 25 sec
Loading image into memory...DONE: 25 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 25 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 25 sec
Clearing memory...DONE: 17 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 26 sec
Loading image into memory...DONE: 25 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 25 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 25 sec
Loading image into memory...DONE: 25 sec
Clearing memory...DONE: 19 sec
Loading image into memory...DONE: 18 sec
Clearing memory...DONE: 25 sec
Loading image into memory...DONE: 26 sec
Clearing memory...DONE: 18 sec

问题

  1. 这个 Windows 是否以错误的方式处理内存操作 处理巨大的 std::vectors?
  2. 是不是 std::vectors 执行得很糟糕 海量数据,是设计使然?
  3. 我是不是完全误解了什么?
  4. 是否有任何其他明显的 std 容器我应该改用(我需要从不同线程通过 x 和 y 中的索引访问图像数据)?
  5. 还有其他好的解释和建议的解决方案吗?

最佳答案

我做错的是我为图像中的每一行调用 vector 分配器(数千次)。当首先将整个事物分配为一个 vector ,然后将不同的行映射到大 vector 中的正确位置时,问题就解决了。

感谢@PaulMcKenzie 的回答,为我指明了正确的方向。

关于c++ - std::vector 在加载/清除大量数据时变得越来越慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40783882/

相关文章:

c++ - 当我们复制/分配派生类对象时,如何在继承中复制基类成员?

C - "char var[]"和 "char *var"之间的区别?

c# - 监控 Windows 中的常规键盘快捷键(例如按两次 Ctrl 调出 Google 桌面搜索)?

arrays - 查询 MongoDB 中的整个对象数组

arrays - Sumproduct公式返回#VALUE!当最后一个数组引用每行中都有公式的列时发生错误。 MS Excel 2010

windows - Azure 报告

windows - 如何使用延迟变量扩展从字符串中引用变量

c++ - 如何使用其他类作为一个类的成员?

c++ - 列表迭代器功能障碍

c++ - 如何使用VBO进行变形?