c - 搜索最大平方算法中的优化函数
问题描述
我对优化有点陌生,我正在参加一场友好的比赛,以编写最快的算法来在有障碍物的领域中找到一个正方形。我认为我的算法非常快(在 10k * 10k 网格中 2.07 秒,密度为 70%),但我想让它更快。我最常用的功能是找到正方形中给定坐标的最大尺寸。这里是 :
int max_size(int i, int j, int **tab, int offset)
{
int a;
a = offset;
if (i > 0 && j > 0)
{
while (i + a < g_ymax && j + a < g_xmax && tab[i + a][j + a] - tab[i + a][j - 1] - tab[i - 1][j + a] + tab[i - 1][j - 1] == 0)
a++;
return (a);
}
else if (i > 0 && j == 0)
{
while (i + a < g_ymax && j + a < g_xmax && tab[i + a][j + a] - tab[i - 1][j + a] == 0)
a++;
return (a);
}
else if (i == 0 && j > 0)
{
while (i + a < g_ymax && j + a < g_xmax && tab[i + a][j + a] - tab[i + a][j - 1] == 0)
a++;
return (a);
}
else
{
while (i + a < g_ymax && j + a < g_xmax && tab[i + a][j + a] == 0)
a++;
return (a);
}
}
所以这很丑陋,我想对其进行优化。是否会使其成为内联函数的帮助?我试图运行一些测试,但我没有看到太大的差异。
解决方案
首先,在没有考虑特定系统的情况下谈论性能或手动优化没有多大意义。通常,为了比该系统的编译器进行更好的优化,您必须是该特定系统的专家。
但是让我们假设这是一些主流的高端系统,如 x86、PowerPC 或 ARM。到目前为止,对性能最重要的是网格如何存储在内存中。
您拥有int **tab
并将其视为二维数组,这是代码异味。这很可能意味着tab
指向一些基于指针的查找表,可能在堆上分配。访问这样的查找表将在具有数据高速缓存存储器的系统上造成显着的性能损失,因为数据的分段将阻碍有效的数据高速缓存利用。有关如何从根本上提高这方面性能的建议,请参阅正确分配多维数组。
将网格移动到连续内存后,下一步是确保以这样的方式对其进行迭代,即最右边的维度是最频繁更改的维度。也就是说,given array[i][j]
确保进行迭代,以便j
成为最频繁更改的迭代器。这也与高速缓存内存的使用以及可能的对齐有关。
您可以通过减少比较次数来获得较小的性能提升,例如使用真值表。比较越少,分支预测越好。
内联函数确实可能会带来轻微的性能提升,尽管编译器应该能够在那里做出更好的决定,因为内联是以牺牲可执行文件大小和内存使用为代价的。
如果 10k*10k 是最大值,则可以通过交换 来获得较小的性能提升int
,uint_fast16_t
尽管这主要是针对 8 位和 16 位 CPU 的优化。
推荐阅读
- signalr - AspNetCore / SignalR - 从 SignalR 集线器服务器返回 HttpResponseMessage 导致 InvalidDataException
- arrays - 仅当 counter_name 匹配时如何从 JSON 数据下方提取 counterid 并将 counterid 添加到 shell 脚本中的另一个文件
- ssh - 两个 Mercurial 回购。在远程机器上——一个可以通过 ssh 克隆;另一个,不是
- laravel - 如何在 Laravel Vue 中沿侧引导程序使用 zurb 基础?
- flutter - 如何在 SliverChildListDelegate 中使用 FirestoreAnimatedList?
- android - E/CRASH(7870):信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR),故障地址 0000007c2f67f818
- amazon-web-services - AWS ASG 冷却期和扩展策略中的预热期有什么区别?
- javascript - 在 highcharts 散点图中添加自定义变量作为工具提示
- javascript - 指南针使用博览会记录磁力计的值?
- java - 使用拖放 android 在 PDF 上添加签名或图像(获取 x 和 y 坐标)