c++ - 加快 C++ 中 double 的比较

标签 c++ arrays visual-studio-2012 double binary-search

<分区>

我有一个函数,它使用二进制搜索来查找已排序的 double 组中的索引,使得“搜索值”大于或等于数组中该索引处的值,但严格小于数组中的值如果按升序排序,则为后续索引处的数组。输入数组可以按升序或降序排序。

我在 Microsoft Visual Studio 2012 上分析了我的代码,它显示 12% 的时间花在了这个函数上,而 8% 的时间花在了比较“搜索值”和数组中的值上。我想探索加速此功能的可能性。

/**
    Binary Search algorithm for a sorted array of doubles
    _sortedArr could be sorted ascending or descending
    Find the index in the array _sortedArr such that:
    _sortedArr[lowerIndex] <= _valToFind < _sortedArr[lowerIndex+1]
*/
size_t findInArray(const double _sortedArr[], size_t _len, double _valToFind)
{
    size_t startIndex = 0;

    if( _len <= 1 ) return startIndex;

    // Determine if the array is sorted ascending or descending
    unsigned int isAscending = (_sortedArr[_len-1] > _sortedArr[startIndex]);

    // To avoid looping through the array, detect edge cases first
    if( isAscending ) {
        if( _valToFind <  _sortedArr[startIndex+1] ) return startIndex;
        if( _valToFind >= _sortedArr[_len-1] ) return _len-1;
    } else {
        if( _valToFind >  _sortedArr[startIndex+1] ) return startIndex;
        if( _valToFind <= _sortedArr[_len-1] ) return _len-1;
    }

    size_t lowerIndex = startIndex + 1;
    size_t upperIndex = _len - 1; 
    size_t midIndex = 0;

    // Binary search loop
    while (upperIndex - lowerIndex > 1)
    {
        midIndex = (upperIndex + lowerIndex) >> 1; // (upperIndex+lowerIndex)/2

        // 8% of time spent executing the if-clause
        if (_valToFind >=  _sortedArr[midIndex] == isAscending)
            lowerIndex = midIndex;
        else
            upperIndex = midIndex;
    }

    return lowerIndex;
}

下面是测试该功能的方法:

int main (int argc, char *argv[])
{
    const double arr[] = {-3.0000000000000000, -2.5714285714285716, -2.1428571428571432,
                      -1.7142857142857146, -1.2857142857142860, -0.85714285714285743,
                      -0.42857142857142888, -3.3306690738754696e-016, 0.42857142857142821,
                      0.85714285714285676, 1.2857142857142854, 1.7142857142857140,
                      2.1428571428571423, 2.5714285714285707, 2.9999999999999991};

    size_t index = findInArray(arr, 15, 0.0);
    std::cout << "Index is: " << index << std::endl;
    return 0;
}

当我更改 if 子句(此处花费 8% 的时间)以使用小于比较时,没有明显的性能改进:

if (!(_valToFind <  _sortedArr[midIndex]) == isAscending)

此更改在反汇编中的唯一区别是使用“ja”而不是 jb。

如有任何想法,我们将不胜感激。

最佳答案

也许尝试删除代码中的条件分支。

size_t luIndex[2] = { startIndex + 1, _len - 1 };
size_t &lowerIndex = luIndex[0];
size_t &upperIndex = luIndex[1]; 
size_t midIndex = 0;

// Binary search loop
while (upperIndex - lowerIndex > 1)
{
    midIndex = (upperIndex + lowerIndex) >> 1; // (upperIndex+lowerIndex)/2
    luIndex[_valToFind >= _sortedArr[midIndex] != isAscending] = midIndex;
}

return lowerIndex;

关于c++ - 加快 C++ 中 double 的比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30718164/

相关文章:

c++ - 从 Visual Studio 2012 中浏览 Qt 5.1.1 基本源 - 将 .pro 转换为 .sln 文件

c# - .NET 4.5 的 connectionType 版本和公钥的 log4net 配置

c++ - 用于快速射线相交的线段容器? (二维)

arrays - 部分选择多维 systemverilog 数组作为 1D 向量

Objective-C 从对象数组中创建逗号分隔字符串的最简单方法

分配后未更新 C++ 字符串大小

asp.net-mvc-3 - DotNetOpenAuth.Asp 无法在 MVC4 应用程序单元测试中加载程序集或其依赖项之一

c++ - 为什么 Clang 将显式强制转换解释为隐式强制转换?

c++ - 迭代非增量枚举

c++ - 如何从字符串中删除第一个单词?