Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.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/2/visual-studio-2010/4.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++;使用c+表现不佳+;互操作?_C++_Visual Studio 2010_C++ Cli - Fatal编程技术网

C++ 为什么原生c++;使用c+表现不佳+;互操作?

C++ 为什么原生c++;使用c+表现不佳+;互操作?,c++,visual-studio-2010,c++-cli,C++,Visual Studio 2010,C++ Cli,我在下面发布了一些代码,以测试使用Visual Studio 2010从本机c++和c++/cli调用方法的性能(时间以毫秒为单位)。我有一个独立的本地C++项目,它被编译成DLL。当我从C++调用C++时,得到的结果比管理的同行快得多(大约4X)。但是,当我从C++调用CLI C++时,性能会慢10X。 这是从C++到CLI调用本地C++的预期行为吗?我的印象是不应该有显著的差异,但这个简单的测试却显示了不同。这是否是C++与C++/CLI编译器之间的优化差异? 更新 我对cpp做了一些更新,

我在下面发布了一些代码,以测试使用Visual Studio 2010从本机c++c++/cli调用方法的性能(时间以毫秒为单位)。我有一个独立的本地C++项目,它被编译成DLL。当我从C++调用C++时,得到的结果比管理的同行快得多(大约4X)。但是,当我从C++调用CLI C++时,性能会慢10X。

这是从C++到CLI调用本地C++的预期行为吗?我的印象是不应该有显著的差异,但这个简单的测试却显示了不同。这是否是C++与C++/CLI编译器之间的优化差异? 更新

我对cpp做了一些更新,这样我就不会在一个紧循环中调用一个方法(如Reed Copsey所指出的),结果证明中的性能差异是微不足道的。当然,这取决于交互操作是如何完成的

.h

#ifndef CPPOBJECT_H
#define CPPOBJECT_H

#ifdef CPLUSPLUSOBJECT_EXPORTING
    #define CLASS_DECLSPEC __declspec(dllexport)
#else
    #define CLASS_DECLSPEC __declspec(dllimport)
#endif

class CLASS_DECLSPEC CPlusPlusObject
{
public:
    CPlusPlusObject(){}
    ~CPlusPlusObject(){}

    void sayHello();
    double getSqrt(double n);
    // Update
    double wasteSomeTimeWithSqrt(double n);
};

#endif
.cpp

#include "CPlusPlusObject.h"
#include <iostream>

void CPlusPlusObject::sayHello(){std::cout << "Hello";}
double CPlusPlusObject::getSqrt(double n) {return std::sqrt(n);}
double CPlusPlusObject::wasteSomeTimeWithSqrt(double n)
{
    double result = 0;
    for (int x = 0; x < 10000000; x++)
    {
        result += std::sqrt(n);
    }
    return result;
}
#包括“cpluplusobject.h”
#包括
void CPlusPlusObject::sayHello(){std::cout Start();
而(秒表->延时毫秒<1200){n+=0.001;}
秒表->重置();
对于(int x=0;x开始();
cpluplusobject cpluplusobject;
n+=cplusplusObject.wasteSomeTimeWithSqrt(123.456);
/*for(int i=0;i<重复;i++)
{
n+=cplusplusObject.getSqrt(123.456);
}*/
秒表->停止();
系统::控制台:WriteLine(“C++/CLI调用”本地C++ C++“+秒表”>“Eclipse毫秒”+“MS”;
秒表->重置();
}
返回n;
}
双cppclitocharp()
{
双n=0;
System::Diagnostics::Stopwatch^Stopwatch=gcnew System::Diagnostics::Stopwatch();
秒表->开始();
而(秒表->延时毫秒<1200){n+=0.001;}
秒表->重置();
对于(int x=0;x开始();
CSharp::CSharpObject^CSharpObject=gcnew CSharp::CSharpObject();
for(int i=0;i<重复;i++)
{
n+=cSharpObject->GetSqrt(123.456);
}
秒表->停止();
System::Console::WriteLine(“c++/cli调用c#take”+“秒表->elapsedmillesocks+“毫秒”);
秒表->重置();
}
返回n;
}
双cppcli()
{
双n=0;
System::Diagnostics::Stopwatch^Stopwatch=gcnew System::Diagnostics::Stopwatch();
秒表->开始();
而(秒表->延时毫秒<1200){n+=0.001;}
秒表->重置();
对于(int x=0;x开始();
cplupluscliobject cplupluscliobject;
for(int i=0;i<重复;i++)
{
n+=cplupluscliobject.getSqrt(123.456);
}
秒表->停止();
System::Console::WriteLine(“c++/cli执行了”+秒表->ElapsedMilliseconds+“毫秒”);
秒表->重置();
}
返回n;
}
int main()
{
双n=0;
n+=cppclitopp();
n+=cppclitocharp();
n+=cppcli();
系统::控制台::写线(n);
System::Console::ReadKey();
}
<>但是,当我从C++ C++调用C++时,性能会慢10X。 桥接CLR和本机代码需要封送处理。当从C++/CLI转到本机方法调用时,每次方法调用都会有一些开销


开销(在本例中)如此之大的唯一原因是您在一个紧密循环中调用了一个非常快速的方法。如果要批处理该类,或者调用运行时间明显较长的方法,您会发现开销非常小。

这些微基准测试非常危险。您努力避免了典型的基准测试错误,但仍然落入了经典陷阱。您的意图是测量方法调用开销,但实际情况并非如此。抖动优化器能够使用标准的代码优化技术,如代码提升和方法内联。只有在查看生成的机器代码时,才能真正看到这一点。调试+窗口+反汇编窗口

我用VS2012测试了这一点,它是启用抖动优化器的32位版本。C++/CLI代码最快,耗时约128毫秒:

000000bf  fld         qword ptr ds:[01212078h] 
000000c5  fsqrt 
000000c7  fstp        qword ptr [ebp-20h] 
//
// stopWatch->Start() call elided...
//
            n += cPlusPlusCliObject.getSqrt(123.456);
000000f5  fld         qword ptr [ebp-20h] 
000000f8  fadd        qword ptr [ebp-14h] 
000000fb  fstp        qword ptr [ebp-14h] 
        for (int i = 0; i < repetitions; i++)
000000fe  dec         eax 
000000ff  jne         000000F5 
000000 BF fld qword ptr ds:[01212078h]
000000 C5 fsqrt
000000 C7 fstp qword ptr[ebp-20h]
//
//秒表->开始()调用elided。。。
//
n+=cplupluscliobject.getSqrt(123.456);
000000 F5 fld qword ptr[ebp-20h]
000000 F8 fadd qword ptr[ebp-14h]
000000 FB fstp qword ptr[ebp-14h]
for(int i=0;i<重复;i++)
000000 FE十二月eax
000000 FF jne 000000 F5
换句话说,std::sqrt()调用被从循环中提升出来,而内部循环只是从生成的值执行加法。没有方法调用。还要注意,它实际上并没有度量sqrt()调用所需的时间:)

使用C#方法调用的循环速度稍慢,大约需要180毫秒:

000000ea  fld         qword ptr ds:[01211EC0h] 
000000f0  fsqrt 
000000f2  fadd        qword ptr [ebp-14h] 
000000f5  fstp        qword ptr [ebp-14h] 
        for (int i = 0; i < repetitions; i++)
000000f8  dec         eax 
000000f9  jne         000000EA 
000000 EA fld qword ptr ds:[01211EC0h]
000000 f0 fsqrt
000000 F2 fadd qword ptr[ebp-14h]
000000 F5 fstp qword ptr[ebp-14h]
for(int i=0;i<重复;i++)
000000 F8十二月eax
000000 F9 jne 000000 EA
只是对Math::Sqrt()的内联方法调用,它没有被提升。不知道为什么,抖动优化器执行的优化确实包含时间因素

我不会发布互操作调用的代码。但是是的,由于实际需要进行函数调用,需要约380毫秒,非托管代码无法内联,加上防止垃圾收集器
000000ea  fld         qword ptr ds:[01211EC0h] 
000000f0  fsqrt 
000000f2  fadd        qword ptr [ebp-14h] 
000000f5  fstp        qword ptr [ebp-14h] 
        for (int i = 0; i < repetitions; i++)
000000f8  dec         eax 
000000f9  jne         000000EA