在C ++中检查数组位置是否为空的CPU高效方法

时间:2013-12-23 15:46:53

标签: c++ arrays

我编写的程序需要检查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方法来执行空值检查操作?

5 个答案:

答案 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)
}