我正在努力为建立泊松方程的数值求解器进行两次优化之间的决定。
基本上,我有一个二维数组,我需要n
在第一行加倍,n/2
在第二行n/4
中,依此类推...... / p>
现在我的困难在于决定是否使用连续的2d数组grid[m][n]
,对于大的n
,它会有许多未使用的零,但可能会降低缓存未命中的几率。另一种更有效的内存方法是动态地将指针数组分配给大小逐渐减小的数组。这在内存存储方面效率要高得多,但是它可能会阻碍性能吗?
我认为我不清楚这种情况下的权衡取舍。有人可以帮忙吗?
作为参考,我在每种情况下制作了一个很好的内存要求图:
答案 0 :(得分:2)
构建一个遵循您设置的规则的自定义数组。
实现将使用简单的1d连续数组。您将需要一个函数,它将返回给定行的数组的开始。像这样:
int* Get( int* array , int n , int row ) //might contain logical errors
{
int pos = 0 ;
while( row-- )
{
pos += n ;
n /= 2 ;
}
return array + pos ;
}
n
与您描述的相同,并且在每次迭代时向下舍入。
您必须每整行只调用一次此函数。
此函数永远不会花费更多的O(log n)时间,但如果您愿意,可以用单个表达式替换它:http://en.wikipedia.org/wiki/Geometric_series#Formula
答案 1 :(得分:2)
这个没有硬性和快速的答案。如果你的算法需要的内存比预期的要多,那么你需要找到一个可能较慢但符合你约束条件的内存。
除此之外,唯一的选择是实现两者,然后比较他们的表现。如果保存内存导致10%的减速是可以接受的吗?如果使用更多内存的版本速度提高50%,但只能在最大的计算机上运行?这些是我们在计算机科学中必须解决的问题。但是只有拥有数字后才能看到它们。否则,你只是在猜测,并且在优化方面我们的直觉是相当多的时间。
答案 2 :(得分:1)
您可以使用单个数组并自己计算偏移量
size_t get_offset(int n, int row, int column) {
size_t offset = column;
while (row--) {
offset += n;
n << 1;
}
return offset;
}
double * array = calloc(sizeof(double), get_offset(n, 64, 0));
通过
访问array[get_offset(column, row)]