Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;优化if/else条件_C++_Performance_Assembly - Fatal编程技术网

C++ C++;优化if/else条件

C++ C++;优化if/else条件,c++,performance,assembly,C++,Performance,Assembly,我只有一行代码,它占用了应用程序运行时的25%-30%。它是std::set的小于比较器(set是用红黑树实现的)。 它在28秒内被调用了大约1.8亿次 struct Entry { const float _cost; const long _id; // some other vars Entry(float cost, float id) : _cost(cost), _id(id) { } }; template<class T> st

我只有一行代码,它占用了应用程序运行时的25%-30%。它是std::set的小于比较器(set是用红黑树实现的)。 它在28秒内被调用了大约1.8亿次

struct Entry {
  const float _cost;
  const long _id;

  // some other vars

    Entry(float cost, float id) : _cost(cost), _id(id) {
    } 
};



template<class T>
struct lt_entry: public binary_function <T, T, bool>
{
    bool operator()(const T &l, const T &r) const
    {
        // Most readable shape
        if(l._cost != r._cost) {
            return r._cost < l._cost;
        } else {
            return l._id < r._id;
        }
    }
};
struct条目{
施工浮动成本;
const long_id;
//其他一些Var
分录(浮动成本,浮动id):\u成本(成本),\u id(id){
} 
};
模板
结构lt_项:公共二进制函数
{
布尔运算符()(常数T&l,常数T&r)常数
{
//最易读的形状
如果(l._成本!=r._成本){
返回剩余成本<剩余成本;
}否则{
返回l.\u id
条目应按成本排序,如果成本相同,则按其id排序。 对于最小值的每次提取,我有许多插入。我曾考虑过使用斐波那契堆,但有人告诉我,它们理论上很好,但存在高常数问题,而且实现起来相当复杂。由于insert是在O(log(n))中,所以运行时的增长几乎是恒定的。所以我认为坚持拍摄是可以的

为了提高性能,我尝试用不同的形状来表达:

return l._cost < r._cost || r._cost > l._cost || l._id < r._id;

return l._cost < r._cost || (l._cost == r._cost && l._id < r._id);
返回l.|成本l.|成本| l.| id
即便如此:

typedef union {
    float _f;
    int _i;
} flint;

//...

flint diff;
diff._f = (l._cost - r._cost);
return (diff._i && diff._i >> 31) || l._id < r._id;
typedef联合{
浮动(f),;
int_i;
}燧石;
//...
燧石差;
差异f=(l._成本-r._成本);
返回(diff._i和&diff._i>>31)| l._id
但是编译器似乎已经足够聪明了,因为我还没有能够改进运行时

我也考虑过苏格兰和南方能源公司,但这个问题实际上并不适用于苏格兰和南方能源公司

部件看起来有点像这样:

movss  (%rbx),%xmm1
mov    $0x1,%r8d
movss  0x20(%rdx),%xmm0
ucomiss %xmm1,%xmm0
ja     0x410600 <_ZNSt8_Rb_tree[..]+96>
ucomiss %xmm0,%xmm1
jp     0x4105fd <_ZNSt8_Rb_[..]_+93>
jne    0x4105fd <_ZNSt8_Rb_[..]_+93>
mov    0x28(%rdx),%rax
cmp    %rax,0x8(%rbx)
jb     0x410600 <_ZNSt8_Rb_[..]_+96>
xor    %r8d,%r8d
movss(%rbx),%xmm1
mov$0x1,%r8d
MOVS 0x20(%rdx),%xmm0
UCOMIST%xmm1,%xmm0
ja 0x410600
UCOMIST%xmm0,%xmm1
jp 0x4105fd
jne 0x4105fd
mov 0x28(%rdx),%rax
cmp%rax,0x8(%rbx)
jb 0x410600
异或%r8d,%r8d
我对汇编语言有一点点的经验,但不是很多

我认为挤出一些表现是最好的(唯一的?),但这真的值得努力吗?你能看到任何可以节省一些周期的快捷方式吗

代码将在多核intel机器上运行的平台是带有GCC4.6(-stl=c++0x)的Ubuntu12。只有boost、openmp和tbb库可用。30秒的基准测试是在我4岁的笔记本电脑(Core2Duo)上进行的

我真的被困在这个问题上了,它看起来很简单,但却花了那么多时间。几天以来,我一直在绞尽脑汁思考如何改进这条线路

你能给我一个如何改进这部分的建议吗,或者说它已经处于最佳状态了

编辑1:使用Jerry的建议后,我的速度提高了约4.5秒。
编辑2:在尝试boost Fibonacci堆之后,对比了1.74亿次对小于函数的调用。

我本身没有答案-只有几个想法:

  • 如果您使用的是GCC,我会使用
  • 您确定您没有处理成本组件的非规范化数字吗

  • 我很难相信:

    a) 比较功能在30秒内运行1.8亿次

    b) 比较函数使用25%的cpu时间

    都是真的。即使是Core 2 Duo也应该能够在不到一秒钟的时间内轻松运行1.8亿次比较(毕竟,有人声称它可以实现12000次MIPS,如果这真的意味着什么的话)。因此,我倾向于相信,在分析软件的比较中,还有其他一些东西。(例如,为新元素分配内存。)

    但是,您至少应该考虑一下STD::SET不是您正在寻找的数据结构的可能性。如果在实际需要排序值(甚至是最大值)之前进行了数百万次插入,那么最好将这些值放入向量中,这是一种在时间和空间上都非常便宜的数据结构,并根据需要对其进行排序

    如果你真的需要这个集合,因为你担心冲突,那么你可能会考虑一个无序的集合,它稍微便宜,但不像向量那么便宜。(正是因为向量不能保证你的唯一性。)但老实说,看看这个结构定义,我很难相信唯一性对你很重要

    “基准”

    在我的小型Core i5笔记本电脑上(我想它与OP的机器不在同一个级别),我运行了一些测试,将1000万个随机唯一条目(仅包含两个比较字段)插入到std::set和std::vector中。最后,我对向量进行排序

    我做了两次;一次使用随机生成器产生可能唯一的成本,一次使用生成器产生正好两种不同的成本(这会使比较变慢)。1000万次插入的结果比OP报告的结果略多

                  unique cost         discrete cost
               compares     time    compares     time
    set       243002508    14.7s   241042920    15.6s   
    vector    301036818     2.0s   302225452     2.3s
    
    为了进一步隔离比较时间,我使用std::sort和std::partial_sort重新定义了向量基准,使用了10个元素(基本上是前10个元素的选择)和10%的元素(即一百万)。更大的部分_排序的结果让我惊讶——谁会想到对一个向量进行10%的排序会比对所有向量进行排序慢——但它们表明,算法成本比比较成本要重要得多:

                         unique cost         discrete cost
                      compares     time    compares     time
    partial sort 10   10000598     0.6s    10000619     1.1s
    partial sort 1M   77517081     2.3s    77567396     2.7s
    full sort        301036818     2.0s   302225452     2.3s   
    
    结论:比较时间越长,但以容器操作为主。在总共52秒的计算时间内,1000万次集合插入的总成本是显而易见的。1000万个向量插入的总成本就不那么引人注目了

    小纸条,不管它值多少钱

    我从汇编代码中得到的一点是,你不是savin
    struct Entry
    {
        double cost_;
        long id_;
        long long sortingId_;
    
      // some other vars
    
        Entry( double cost, float id )
            : cost_( cost ), id_( id ), sortingId_( 1e9*100*cost + id )
        {} 
    };
    
    struct __attribute__ ((__packed__)) __attribute__((aligned(8)) Entry {
      // Do *not* reorder the following two fields or comparison will break.
      const int32_t _id;
      const float _cost;
    
      // some other vars
    
        Entry(long id, float cost) : _cost(cost), _id(id) {} 
    };
    
    bool operator<(Entry const &a, Entry const &b) { 
       return *(int64_t const *)&a < *(int64_t const *)&b;
    }
    
    int main() { 
        Entry a(1236, 1.234f), b(1234, 1.235f), c(1235, 1.235f);
    
        std::cout << std::boolalpha;
    
        std::cout << (b<a) << "\n";
        std::cout << (a<b) << "\n";
        std::cout << (b<c) << "\n";
        std::cout << (c<b) << "\n";
        return 0;
    }
    
    false
    true
    true
    false