如何在 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:在启用优化的情况下构建代码。 您似乎在i
和j
不变的地方频繁地计算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++ 模板来避免临时对象? [关闭]