我编写的程序需要检查2D数组中的数百万个点,看它们是否为空。这是我正在使用的代码:
Particle *particleGrid[1920][1080];
bool Sensor::checkForParticle(int x, int y) {
if (x > 1920 || x < 0) return 0;
if (y > 1080 || y < 0) return 0;
if (mainController->particleGrid[x][y] != NULL) {
return 1;
}
return 0;
}
这个函数使用整个应用程序中最多的CPU(大约70%的应用程序的CPU使用率是由于这个功能),甚至超过我对Bresenham线条绘制算法的实现(示例函数在每个点都被调用)由Bresenham算法生成的线)。是否有更高效的CPU方法来执行空值检查操作?
答案 0 :(得分:2)
如果在循环中调用它,你可以在不检查参数的情况下逃脱。当你检查内存位置关闭的数据时,它也将是更快的行,这将减少缓存命中。
答案 1 :(得分:2)
如果与无符号文字进行比较,则免费检查0,因为转换为无符号时负数最终会非常大。此外,您不需要所有这些ifs:
bool Sensor::checkForParticle(int x, int y)
{
return (x < 1920u) && (y < 1080u) // note both "u" suffixes for unsigned
&& (mainController->particleGrid[x][y] != NULL);
}
顺便说一下,为什么你的数组按列主要顺序排列?你的外环是x还是y?如果他们在y上,由于缓存友好性,切换到row-major将显着提高效率:
Particle *particleGrid[1080][1920];
bool Sensor::checkForParticle(int x, int y)
{
return (x < 1920u) && (y < 1080u)
&& (mainController->particleGrid[y][x] != NULL); // note switched order
}
答案 2 :(得分:0)
如果2D阵列稀疏,这样的东西可以帮助你加快紧密循环:
Particle *particleGrid[1920][1080];
// somewhere before your tight loop
std::map<std::pair<unsigned int, unsigned int>, Particle*> createCache()
{
std::map<std::pair<unsigned int, unsigned int>, Particle*> cache;
for (unsigned int i = 0; i < 1920; ++i)
{
for (unsigned int j = 0; j < 1080; ++j)
{
if (mainController->particleGrid[i][j])
{
std::pair<unsigned int, unsigned int> coord = std::make_pair(i, j);
cache[coord] = mainController->particleGrid[i][j];
}
}
}
return cache;
}
// then this is called in your tight loop
bool Sensor::checkForParticle(unsigned int x, unsigned int y, const std::map<std::pair<unsigned int, unsigned int>, Particle*>& cache)
{
std::pair<unsigned int, unsigned int> coord = std::make_pair(x, y);
return cache.find(coord) != map.end();
}
如果它不稀疏,这根本没有帮助。
答案 3 :(得分:0)
步骤1:将一致性检查提升出循环:
bool Sensor::uncheckedCheckForParticle(int x, int y) {
return mainController->particleGrid[y][x];
}
如果您真的需要防范草率编程,可以在功能中assert()
和/或保护呼叫站点。我敢打赌,这将显着提高性能。
第2步:制作现在简单的函数inline
。
答案 4 :(得分:0)
你可以将数组从二维展平为一维(遗憾的是,这可能需要在代码中的其他地方进行重构):
Particle *particleGrid[1920 * 1080];
bool Sensor::checkForParticle(int x, int y) {
return (mainController->particleGrid[x * 1080 + y] != NULL)
}