在C中有效地使用大型数组

时间:2015-04-10 20:03:35

标签: c arrays

我正在开发一个使用4D阵列的C程序。我目前实现如下:

main.h

extern float data[31][31][25][100]; 

的main.c

float data[31][31][25][100] = {{.....},{......},.....}; 

int main()
{
double sum; 

for(i=0;i<31;i++)
for(j=0;j<31;j++)
for(k=0;k<25;k++)
for(l=0;l<100;l++)
  sum += data[i][j][k][l];
}

总和是作为占位符...在它的位置将是一个4D查找表的东西。我这样实现,因为我不想从磁盘加载这些数据。在未来我可能会使用数据库或其他东西来加载一部分数据,但现在我需要使用整个数据集。

所以我的问题是......有没有什么方法可以让我更有效率和/或我可以使这个可执行文件更小(可执行文件目前是~5 MB。这最终将在四核手臂板上运行。

我尝试过的唯一一件事就是使用gcc进行优化。我已经尝试了-O2和-O4并且我得到了以下错误。没有-O2,它编译并运行良好。有任何想法吗?我还没有真正查找所有优化选项...只是尝试了我在网上看过的东西。

ld: can't link with a main executable file 'test' for architecture x86_64

感谢您的帮助!

评论的回答:

  1. 无法以编程方式生成数据。生成数据 通过离线模拟
  2. 我已更新为代码,以显示该数组位于主数据之外并且是全局的
  3. @ js1你说它接近9 MB,我正在使用几个版本的代码,5 MB可执行文件是一个有100万+元素的。
  4. @ pm100我想这是一个很好的问题...我在PC上对这些代码进行原型设计并且工作正常......但实际上它最终会在嵌入式平台上运行。我们目前正在计划用pixhawk进行测试(这是用于遥控车辆的扶手板,我们的生产板将更快,并且有更多的内存)。我试图尽可能高效和优化,以减轻在手臂平台上运行的任何潜在问题。
  5. @ user3629249是的,我们正在mac osx上构建我们的代码然后 完成后编译ARM。
  6. @mcleod_ideafix会加载一个包含2百万的二进制文件 pts会更快吗?老实说,我甚至没有考虑过二进制文件...我 会尝试像这样实施。每次调用程序时,它 需要访问这些数据的某些部分。它不需要所有2 百万分,但输入决定了它需要的阵列的哪一部分 是可变的。理想情况下,我只想加载数组的一部分 我需要的。但是,当我尝试它,加载文件和 搜索正确的阵列需要比此电流长2-3倍 做法。我想知道我是不是搞砸了什么 加载/搜索文件。
  7. 评论的答案pt2: 数据不稀疏...我想不出任何简单的方法来减少pts的数量而不降低模型的保真度。数据是固定的,永远不会改变。将要改变的是使用数据的输入,这将导致使用4D数据的不同部分。

    就数据而言:它实际上是飞行器的轨迹预测数据。使用在群集上运行的非线性模拟离线生成4D数据 所以我的嵌入式程序必须做的是将当前车辆状态(位置,方向等)与4D数据一起生成估计轨迹。由于专有原因,我无法真正提供数据集。我希望这能回答一些问题...抱歉模糊不清

    我将处理二进制实现并尝试加载数组的子集。我可能做了一些愚蠢的事情,让它变得非常慢。谢谢大家的评论,它给了我一些新的想法尝试。

3 个答案:

答案 0 :(得分:0)

如果无法以编程方式生成数据,那么当程序启动时,它们必须位于硬盘中的某个位置,并且程序必须以某种方式将数据加载到4D阵列中。

因此,如果您的可执行文件大小为5MB,考虑到包含初始化数据,这是正常的。这种方法的好处是可以加载和初始化数组的操作系统。当程序执行main()函数的第一条指令时,数据已经存在。你只需要使用它。缺点是如果你的程序永远不需要使用数据,他们使用的内存仍然存在,浪费地址空间。

另一方面,您可以将数据放在一个单独的文件中:无论是作为处理过程加载的数据文件,还是程序在需要时加载的动态库,或者映射的二进制文件进入记忆。这样做的好处是,只有在需要时才将数据加载到内存中,仅在实际访问数据时需要额外的地址空间,并在不再需要时释放数据。此外,您的可执行文件将加载更快,因为不需要先前的加载和初始化。这样做的缺点是你的程序必须包含一些程序来在使用它之前加载和初始化4D阵列,还有一些程序在不需要时处理它。

也就是说,对于需要为整个程序生存的静态非程序计算值数组,最有效的方法是将数组声明为全局并在同一声明中初始化它。这将在.data部分中添加一个内存块,其中包含已经采用数组所需格式的初始化数据。在重定位操作期间,该内存块的开头将分配给数组的名称。

答案 1 :(得分:0)

您需要32位浮点精度吗? 例如,16位定点值可以将二进制文件的大小减半。 如果表中存储的值的特征是线性的而不是指数的,那么固定点是以每个存储的信息位的精度存储它们的最有效方式。

每个值24位或12位的不均匀定点表示也是可能的。

您还可以考虑对表格的不同部分使用不同的精度级别。

是否实际使用了查找表的每个值?也许可以省略它的某些子部分。它将以更复杂的数据结构和查找功能为代价来减小尺寸。

另外,您可能希望将查找表声明为“const”。

答案 2 :(得分:0)

就你的查询而言。

我建议您为每个列表使用Tree&#39; s。这将大大减少查询时间(LOG(n))和插入时间以及最多n(log(n))。

这至少可以帮助您的应用程序在运行时更快地移动。

您希望使用体面的数据结构。例如堆或通用B-TREE。