我有一个两阶段过程,在我的模拟程序中构成一个循环。更多或更少,我有以下:对STL向量执行重复操作是否允许“固有并行性”/改进的内存访问?
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
(功能A)和CalcResult
f_B
(函数B),测试是:
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样式x
,y
和z
阵列与std::vector<double>
替代有加速计算或存储器访问的可能性以任何方式?
请不要回答“你自己的基准”...我想要通过基于编译器的“理论基准”来测试方法Test
以获得更好的理解,固有平行度“。
MSalters,它们是相同的,其实。这就是为什么我开始内循环@ j ---这是对唯一坐标对的计算,所以我们只计算N×N坐标空间的一半......关于内存访问的好想法,谢谢......这就是我的想法...我可能会从f_A f_B开始...方法 –
正确,忽略了那一点 - 在这种情况下,您只需要预留(N * N + N)/ 2个元素。仍然是O(N * N)内存访问。 – MSalters