如何在 C++ 中进行耗时的三重组合 [关闭]

Posted

技术标签:

【中文标题】如何在 C++ 中进行耗时的三重组合 [关闭]【英文标题】:How to do a time consuming triple combination in C++ [closed] 【发布时间】:2019-01-15 01:14:01 【问题描述】:

有没有更快的方法在 C++ 中进行以下三元组合,而不是逐个元素地进行常规顺序组合?

const short n = 1000;
float a[n];⋅
for(int i = 0; i<n; i++)⋅
    a[i] = (float)i;

int b = 0;
for(int i = 0; i<n; i++)
    for(int j = 0; j<n; j++)
        for(int m = 0; m<n; m++)
            b += a[i]*a[j]*a[m];

cout<<"b: "<<b<<endl;

【问题讨论】:

建议 1:在启用优化的情况下构建代码。 您似乎在ij 不变的地方频繁地计算a[i]*a[j]。您的优化器可能会也可能不会注意到。 当最终结果是int 时,为什么要用整数填充float 数组?只需将a[i],a[j],a[m] 替换为i,j,m,您应该会得到相同的结果 代码在启用优化的情况下大约需要 3 秒。如果您观察到更大的东西,则说明您测量错误或没有提供正确的minimal reproducible example。 另外,您通过溢出b 来调用未定义的行为。 【参考方案1】:

在数学上,您的产品总和可以简化为您的数组的总和,立方。

所以你可以改用这个:

// assuming a is an std::vector or similar
b = std::accumulate(a.begin(), a.end(), 0);
b = b*b*b;

您可以通过玩弄这段代码来说服自己:

#include <iostream>
#include <array>
#include <numeric>

int main()

    auto a = std::array2, 3, 5, 7;

    auto sum = 0;
    for (auto i : a) 
        for (auto j : a) 
            for (auto k : a) 
                sum += i*j*k;
            
        
    

    std::cout << sum << "\n";

    sum = std::accumulate(a.begin(), a.end(), 0);
    std::cout << sum*sum*sum << "\n";

Live on Coliru

您的代码计算的内容基本上如下:

sumi in a( sumj in a( sumk in a( i*j*k ) ) )

这简化为:

sumi in a( i*sumj in a( j*sumk in a(k) ) )
sumi in a( i*sumj in a(j)*sumk in a(k) )
sumi in a(i)*sumj in a(j)*sumk in a(k)
sumi in a(i) ^3

【讨论】:

非常优雅!将其转换为向量算术(如 cmets 中指定的 OP)是否正确? @BenJones OP 说“我们需要计算三元组的点积”。我不知道他的意思是什么,因为点积只需要两个向量。如果他的意思是逐元素乘法,那么是的,同样的简化适用(但结果是一个向量,而不是一个标量)。如果他的意思是标量三倍积,那么我认为它不起作用,但我懒得确认。

以上是关于如何在 C++ 中进行耗时的三重组合 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

编译器如何在继承 C++ 中进行组合?

如何更快地进行三重 foreach?

如何在 C++ 中构建图形用户界面? [关闭]

在进行添加时如何通过使用 c++ 模板来避免临时对象? [关闭]

在 C++ 中处理字符串时如何使用 memset? [关闭]

如何在 C# 中按下停止按钮来停止耗时过长的 UI 线程 [关闭]