Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/vim/5.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++_Rtti_Dynamic Cast - Fatal编程技术网

C++ 动态投影的性能

C++ 动态投影的性能,c++,rtti,dynamic-cast,C++,Rtti,Dynamic Cast,我之前问了一个问题,答案让我写了一些关于dynamic\u cast性能的代码,如下所示,dynamic\u cast比没有dynamic\u cast花费的时间稍大。我没有看到dynamic\u cast花费时间的证据。我写的代码正确吗 代码是: class Animal { public: virtual ~Animal(){}; }; class Cat : public Animal { public: std::string param1; std::stri

我之前问了一个问题,答案让我写了一些关于
dynamic\u cast
性能的代码,如下所示,
dynamic\u cast
比没有
dynamic\u cast
花费的时间稍大。我没有看到
dynamic\u cast
花费时间的证据。我写的代码正确吗

代码是:

class Animal
{
public:
    virtual ~Animal(){};
};

class Cat : public Animal
{
public:
    std::string param1;
    std::string param2;
    std::string param3;
    std::string param4;
    std::string param5;
    int param6;
    int param7;
};

bool _process(Cat* cat)
{
    cat->param1 = "abcde";
    cat->param2 = "abcde";
    cat->param3 = "abcde";
    cat->param4 = "abcde";
    cat->param5 = "abcde";
    cat->param6 = 1;
    cat->param7 = 2;
    return true;
}

bool process(Animal *ptr)
{
    Cat *cat = dynamic_cast<Cat*>(ptr);
    if (cat == NULL)
    {
        return false;
    } 
    _process(cat);
    return true;
}
int main(int argc, char* argv[])
{
    /*
    argv[1] : object num
    */

    if (argc != 2)
    {
        std::cout << "Error: invalid argc " << std::endl;
        return -1;
    }

    int obj_num = atoi(argv[1]);
    if (obj_num <= 0)
    {
        std::cout << "Error: object num" << std::endl;
    }

    int c = 0;
    for (; c < obj_num; c++)
    {
        Cat cat;
        #ifdef _USE_CAST
        if (!process(&cat))
        {
            std::cout << "Error: failed to process " << std::endl;
            return -3;
        }
        #else
        if (!_process(&cat))
        {
            std::cout << "Error: failed to process " << std::endl;
            return -3;
        }

        #endif
    }

    return 0;
}
使用num执行它们,即1,10100…:

$time ./dynamic_cast_test num
$time ./dynamic_cast_no_test num
结果是:

                 dynamic_cast               non_dynamic_cast
num  10,000   
                real    0m0.010s            real    0m0.008s
                user    0m0.006s            user    0m0.006s
                sys     0m0.001s            sys     0m0.001s

     100,000 
                real    0m0.059s            real    0m0.056s
                user    0m0.054s            user    0m0.054s
                sys     0m0.001s            sys     0m0.001s

     1,000,000
                real    0m0.523s            real    0m0.519s
                user    0m0.517s            user    0m0.511s
                sys     0m0.001s            sys     0m0.004s

     10,000,000
                real    0m6.050s            real    0m5.126s
                user    0m5.641s            user    0m4.986s
                sys     0m0.036s            sys     0m0.019s

     100,000,000
                real    0m52.962s           real    0m51.178s
                user    0m51.697s           user    0m50.226s
                sys     0m0.173s            sys     0m0.092s
硬件和操作系统:

OS:Linux
CPU:Intel(R) Xeon(R) CPU E5607  @ 2.27GHz  (4 cores)

我将重新制定我的帖子

您的代码是正确的,并且编译得很好

由于虚拟方法和动态_cast操作符是相关的问题,请从wiki查看这些信息,希望它们会有用

维基:

虚拟调用至少需要额外的索引解引用,并且 有时,与非虚拟呼叫相比,添加了一个“fixup”,即 只需跳转到已编译的in指针。因此,调用虚拟 函数本身比调用非虚拟函数慢。一 1996年进行的实验表明,大约6-13%的 执行时间仅用于分派到正确的函数, 虽然开销可能高达50%。[4]虚拟机的成本 在现代CPU体系结构上,功能可能不太高,因为 更大的缓存和更好的分支预测

此外,在不使用JIT编译的环境中, 虚拟函数调用通常不能内联。当一个编译器 例如,可以将查找和间接调用替换为 每个内联体的有条件执行,这样的优化不会 普通的

为了避免这种开销,编译器通常在任何时候都避免使用vtables 可以在编译时解析调用

因此,上面对f1的调用可能不需要vtable查找,因为 编译器可能能够判断d此时只能保存一个d, D不会覆盖f1。或者编译器(或优化器)可以 检测程序中任何地方都没有B1的子类 这将覆盖f1。对B1::f1或B2::f2的调用可能不会 需要vtable查找,因为指定了实现 显式(尽管它仍然需要“this”-指针修正)


另外,您可能知道,当您在类中声明虚拟方法时,取决于实现,但几乎总是,编译器会隐式地将虚拟方法表作为新成员添加到类中,因此该类的每个实例都会占用更多内存空间,请在有vm的类和没有vm的类上尝试sizeof。

您编写了正确的代码,虽然我不会硬编码的类型是一只猫。为了安全起见,您可以使用命令行参数来决定是构建猫还是构建狗(您也应该实现)。尝试禁用优化,看看它是否发挥了重要作用


最后,需要提醒一句话。评测并不像在计算机上进行测量那样简单,所以您必须意识到,您所做的只是迄今为止的工作。它确实给了您一个想法,但不要认为您得到了任何包含所有内容的答案。

对于初学者来说,您并没有使用优化进行编译。添加
-O3
编译器标志。通常不鼓励使用动态\u cast,因为它表明设计不好,而不是因为它“慢”(这是相对的事情)。如果您尝试使用多个虚拟继承,会怎么样?您应该尝试使用更深层的继承树(可能还有一些多重继承)进行基准测试。然后,您将看到显著的差异这里有一些基准测试:还要注意,现代编译器有时可以优化动态强制转换。问题不在于调用虚拟函数的成本。@Stefano Falasca,我认为是的,因为动态强制转换和虚拟方法是相对的,不是吗?我不会说它们不相关,因为这很难证实。尽管如此,认为DyrimeCype需要RTTI(好的,不是禁用的),而如果RTTI被禁用,你确实可以使用虚拟调度。我倾向于给这个答案A+ 1,这样它就不再有丑陋的负号了。这至少是有用的信息,我看到虚拟函数和动态_cast(某种程度上)是相关的。抱歉,这可能是我的错,但我仍然看不出这是如何回答问题的一部分。@TobiMcNamobi,好吧,idk肯定dynamic_cast操作符是如何深入工作的,你知道吗?我想,不管怎样,动态搜索(当然是在“RTTI关闭”时)都是通过vtable指针进行查找的,所以wiki说vtable查找确实需要成本,但在现代机器上,这并不重要。这就是为什么我相信作者所做的测试让他有点困惑的原因,(“看在上帝的份上,每个人都说dynamic_cast操作符是个恶魔,但我的测试表明它是可以的!”)。Mb我错了。
OS:Linux
CPU:Intel(R) Xeon(R) CPU E5607  @ 2.27GHz  (4 cores)