【问题标题】:Why performance is reduced much when I run a for loop with a count of 5368709120 and few lines of memcpy?为什么当我运行一个计数为 5368709120 和几行 memcpy 的 for 循环时性能会大大降低?
【发布时间】:2021-02-25 05:27:17
【问题描述】:

我正在分配三个大型字节数组并将它们初始化为一些值。我必须对这三个数组之间的每 64 位执行一次操作。我创建了一个 for 循环来遍历这些数组,并使用 memcpy 将连续的 8 字节(64 位)转换为 64 位整数并在它们之间执行操作。后来,计算了for循环所用的时间。我在这里给出了我的代码。

#include <stdio.h> 
#include<iostream>
#include<ctime>
#include<Windows.h>
#include<chrono>
using namespace std;
BYTE* buffer1;
BYTE* buffer2;
BYTE* buffer3;
int main()
{
    unsigned long long offsetValue = 0;
    int64_t data1, data2, data3;
    unsigned long long BufferSize = 5368709120;
    buffer1 = (BYTE*)malloc(BufferSize);
    buffer2 = (BYTE*)malloc(BufferSize);
    buffer3 = (BYTE*)malloc(BufferSize);
    memset(buffer1, 0, BufferSize);
    memset(buffer2, 1, BufferSize);
    memset(buffer3, 1, BufferSize);
    bool overallResult = false;
    bool stopOnFail = false;
    auto start = chrono::steady_clock::now();
    for (unsigned long long i = 0, cycle = 0; i<BufferSize; i += 8, ++cycle)
    {
        long long offset = (offsetValue * 8) + i;
        if (offset> BufferSize - 1)
            break;
        else if (offset< 0)
            continue;
        memcpy(&data1, buffer1 + offset, sizeof(int64_t));
        if (data1 == -1)
            continue;
        memcpy(&data2, buffer2 + offset, sizeof(int64_t));
        memcpy(&data3, buffer3 + offset, sizeof(int64_t));
        int64_t Exor = data2 ^ data3^-1;
        int64_t Or = Exor | data1;
        bool result = Or == -1;

        overallResult &= result;
        if (!result)
        {
            if (stopOnFail)
                break;
        }
    }
    auto ending = chrono::steady_clock::now();
    cout << "For loop Execution time in milliseconds :"
        << chrono::duration_cast<chrono::milliseconds>(ending - start).count()
        << " ms" << endl;
    free(buffer1);
    free(buffer2);
    free(buffer3);
    system("pause");
    return 0;
}

对于 4294967296 的循环计数给了我 760 毫秒的时间。但是对于 5368709120 的循环计数给了我 25000 毫秒的时间。是什么消耗了 for 循环中的时间?我应该如何优化?

【问题讨论】:

    标签: c++ performance for-loop memory memcpy


    【解决方案1】:

    1。您没有在循环外使用值overallResult,因此一个好的优化编译器可以完全优化循环。 MSVC 可能不是那么聪明,但它仍然是一个好主意,例如最后打印出overallResult

    2。您正在分配(并实际使用)3 × 5,368,709,120 字节 = 15 GB。 Windows 10 系统使用远远超过 1 GB 来运行(尤其是与 Visual Studio 结合使用),因此在 16 GB 的系统上,分配 15 GB 将不可避免地导致paging,这很可能是您所观察到的(此外,大约 20..40 倍的减速是内存分页的特征)。

    验证:

    • 打开性能监视器 (perfmon.exe)
    • 添加计数器 -> 分页文件 -> %使用率
    • 运行您的程序

    如果分页计数器 > 0,那么您没有足够的 RAM,并且由于从磁盘读取页面,内存循环会变慢。

    您还可以在 任务管理器 -> 性能 选项卡中查看 RAM 使用情况。

    【讨论】:

    • 不确定 MSVC 有多聪明,但它肯定不会引用循环中的任何缓冲区。我承认,循环本身在 asm 中看起来很傻 - 它是空的。还想指出overallResult &amp;= &lt;anything&gt; 将是错误的,因为您从bool overallResult = false; 开始:) 但相信我 - 它已被 MSVC 优化。
    • @rustyx 分页计数器值始终大于 0。分页百分比使用率约为 7。即使在第一次执行完成后也保持不变。我需要重置还是什么?正如您所说,对于 15GB 阵列大小,RAM 使用量约为 15GB,对于 9GB 阵列大小,RAM 使用量约为 10GB。我认为需要更多的 RAM 大小来提高性能。谢谢。
    • @VladFeinstein 整体结果已初始化为 true,我稍后会在我的应用程序中使用它。 stopOnFail 也设置为 true。我留下了很多逻辑,我只是​​尝试了一小部分代码来单独测试性能。 memcpy 将完全使用所有缓冲区,这会影响性能。编译器优化其他无助于性能的地方。
    猜你喜欢
    • 1970-01-01
    • 2020-01-31
    • 2020-06-25
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多