【问题标题】:Why is 1 for-loop slower than 2 for-loops in problem related to prefix sum matrix?为什么在与前缀和矩阵相关的问题中 1 个 for 循环比 2 个 for 循环慢?
【发布时间】:2021-12-07 12:32:21
【问题描述】:

我最近在做this problem,直接从IOI 2010的第1天任务3翻译过来的,"Quality of life",遇到了一个奇怪的现象。

我正在设置一个 0-1 矩阵并使用它在 1 个循环中计算前缀和矩阵:

for (int i = 1; i <= m; i++)
{
    for (int j = 1; j <= n; j++)
    {
        if (a[i][j] < x) {lower[i][j] = 0;} else {lower[i][j] = 1;}
        b[i][j] = b[i-1][j] + b[i][j-1] - b[i-1][j-1] + lower[i][j];
    }
}

我在 4 次测试中获得了 TLE(超出时间限制)(时间限制为 2.0 秒)。分别使用2个for循环时:

for (int i = 1; i <= m; i++)
{
    for (int j = 1; j <= n; j++)
    {
        if (a[i][j] < x) {lower[i][j] = 0;} else {lower[i][j] = 1;}
    }
}

for (int i = 1; i <= m; i++)
{
    for (int j = 1; j <= n; j++)
    {
        b[i][j] = b[i-1][j] + b[i][j-1] - b[i-1][j-1] + lower[i][j];
    }
}

让我获得完整的交流电(接受)。

我们可以从这里的 4 张图片中看到:

2 个 for 循环代码通常运行得更快一些(即使在已接受的测试用例中),这与我认为单个 for 循环应该更快的逻辑形成鲜明对比。为什么会这样?

完整代码(AC):https://pastebin.com/c7at11Ha(请忽略所有废话和using namespace std;之类的东西,因为这是一场竞争性编程竞赛)。

  • 注意:评委服务器lqdoj.edu.vn 建立在全球竞争性编程竞赛平台dmoj.ca 之上。

【问题讨论】:

  • 您真的需要存储lower 以供以后使用吗?为什么不直接添加int(a[i][j] &gt;= x)
  • @Brannon 不是真的,说实话...哎呀。

标签: c++ performance for-loop prefix-sum


【解决方案1】:

如果您查看assembly,您会发现差异的来源:

  1. 单循环:
{
    if (a[i][j] < x)
    {
        lower[i][j] = 0;
    }
    else
    {
        lower[i][j] = 1;
    }
    b[i][j] = b[i-1][j] 
            + b[i][j-1]
            - b[i-1][j-1]
            + lower[i][j];
}

在这种情况下,存在数据依赖性。分配给b 取决于分配给lower 的值。所以这些操作在循环中按顺序进行——首先分配给lower,然后分配给b。由于依赖关系,编译器无法显着优化此代码。

  1. 将分配分成 2 个循环:

lower 的赋值现在是独立的,编译器可以使用SIMD instructions,从而在第一个循环中提高性能。第二个循环或多或少与原始程序集相似。

【讨论】:

  • 感谢您的回答!我对组装不太熟悉,所以您能否进一步详细说明在这种情况下什么是“simd 指令”以及它们如何影响这里的运行时间?我认为是第 163-212 行的部分有所不同,但我不确定它的作用。
  • @silverfox 单指令多数据。一条指令处理几个打包到一个特殊长寄存器中的输入项,例如一次对几个整数求和。例如,在您的情况下, pcmpgtd 指令一次比较几个数组元素,然后 movdqu 将所有结果(0/1)保存到目标中。 (指令适用于 x86,arm 有自己的 simd 指令)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-29
  • 2017-11-09
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 2019-12-08
  • 2014-08-09
相关资源
最近更新 更多