我有一个两阶段过程,在我的模拟程序中构成一个循环。或多或少我有以下几点:
struct Coordinates
{
double * x, * y, * z;
uint * kind, count;
double GetDist(const uint p1, const uint p2);
};
struct Polynomial
{
double * A, * B;
uint n1, n2;
uint Flatten(const uint i, const uint j);
double CalcResult(double distSq, uint kind1, uint kind2)
{
uint ij = Flatten(kind1, kind2);
double base = B * distSq;
return A[ij]*(pow(base,n2)-pow(base,n1));
}
};
我的问题是如果我写我的代码
struct Model
{
Coordinates c;
Polynomial f;
double DoTest()
{
double result = 0;
uint count = 0;
std::vector<double> distSq;
for (uint i=0; i<c.count; i++)
{
for (uint j=i; j<c.count; j++)
{
result = c.GetDist(i,j);
distSq.push_back(result);
}
}
result = 0;
for (uint i=0; i<c.count; i++)
{
for (uint j=i; j<c.count; j++)
{
result += f.CalcResult(distSq[count], i, j);
count++;
}
}
return result;
}
double DoTest2()
{
double result = 0;
for (uint i=0; i<c.count; i++)
for (uint j=i; j<c.count; j++)
result += f.CalcResult(c.GetDist(i,j), i, j);
return result;
}
}
Test
考虑到对单个数据集的重复操作,是否会在 x86 芯片上自动启用并行性(例如矢量化数学或改进的内存访问)?
否则Test
是一种垃圾方法——它使用额外的存储空间(std::vector<double> distSq;
)并且在代码阅读方面要长得多。从逻辑上讲,它或多或少是相同的,但是如果我们调用GetDist
f_A
(function A) 和CalcResult
f_B
(function B),Test 是:
f_A f_A f_A ... f_A f_B f_B .... f_B
其中较短/较少的内存密集型功能是
f_A f_B f_A f_B .... f_A f_B
-O#
由于生成的矢量化数学运算等,我听说编译的 C 代码中所谓的“固有并行性”。考虑到它,是否Test
可以在 x86 芯片上启用这种编译器派生的并行性(例如矢量化数学或优化的内存访问?)对单个数据集的重复操作?
(否则Test2
是唯一合理的方法,因为它使用更少的内存。)
用替代品替换 c-style x
、y
和z
arraysstd::vector<double>
是否有可能以任何方式加速计算或内存访问?
请不要回答“对自己进行基准测试”......我要求尝试更好地理解是否值得Test
通过基于编译器和“固有并行性”的理论角度的基准测试方法的原因。