Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.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语言中编写整个应用程序,但是性能的原因意味着C++的速度快得多。p> 我对两种不同的代码实现了一些基准(一种是C,另一种是C++),计时显示C++版本是8倍,两种版本都是发布模式,所有优化都是启用的。(实际上,C语言的优点是编译为64位。我忘记在C++定时启用这个)_C#_C++_Performance - Fatal编程技术网

C# 用C+编写性能关键的C代码+; 我目前正在研究一些性能关键代码,我有一个特殊的情况,我喜欢在C语言中编写整个应用程序,但是性能的原因意味着C++的速度快得多。p> 我对两种不同的代码实现了一些基准(一种是C,另一种是C++),计时显示C++版本是8倍,两种版本都是发布模式,所有优化都是启用的。(实际上,C语言的优点是编译为64位。我忘记在C++定时启用这个)

C# 用C+编写性能关键的C代码+; 我目前正在研究一些性能关键代码,我有一个特殊的情况,我喜欢在C语言中编写整个应用程序,但是性能的原因意味着C++的速度快得多。p> 我对两种不同的代码实现了一些基准(一种是C,另一种是C++),计时显示C++版本是8倍,两种版本都是发布模式,所有优化都是启用的。(实际上,C语言的优点是编译为64位。我忘记在C++定时启用这个),c#,c++,performance,C#,C++,Performance,所以我想,我可以用C#编写大部分代码库(C#使得编写非常容易),然后编写性能至关重要的本地版本。在C和C++中测试的特定代码块是处理时间超过95%的关键区域之一。 但是,在这里编写本机代码的建议智慧是什么?我从来没有写过一个调用C++的C++应用程序,所以我不知道该怎么做。我想以一种尽可能降低本机调用成本的方式来实现这一点 谢谢 编辑:下面是我实际要处理的大部分代码。这是一个n体模拟。95-99%的CPU时间将花费在Body.Pairwise()中 我还有一个类,它仅通过以下方法驱动模拟:

所以我想,我可以用C#编写大部分代码库(C#使得编写非常容易),然后编写性能至关重要的本地版本。在C和C++中测试的特定代码块是处理时间超过95%的关键区域之一。 但是,在这里编写本机代码的建议智慧是什么?我从来没有写过一个调用C++的C++应用程序,所以我不知道该怎么做。我想以一种尽可能降低本机调用成本的方式来实现这一点

谢谢

编辑:下面是我实际要处理的大部分代码。这是一个n体模拟。95-99%的CPU时间将花费在Body.Pairwise()中

我还有一个类,它仅通过以下方法驱动模拟:

    public static void Pairwise(Body[] b, int n)
    {
        for (int i = 0; i < n; i++)
            for (int j = i + 1; j < n; j++)
                b[i].Pairwise(b[j]);
    }

    public static void Predict(Body[] b, int n, double dt)
    {
        for (int i = 0; i < n; i++)
            b[i].Predict(dt);
    }

    public static void Correct(Body[] b, int n, double dt)
    {
        for (int i = 0; i < n; i++)
            b[i].Correct(dt);
    }
publicstaticvoid成对(Body[]b,int-n)
{
对于(int i=0;i
主循环看起来就像:

for (int s = 0; s < steps; s++)
{
    Predict(bodies, n, dt);
    Pairwise(bodies, n);
    Correct(bodies, n, dt);
}
for(int s=0;s
以上只是我实际正在开发的一个更大应用程序的最低要求。还有一些事情要做,但最关键的性能问题出现在这三个函数中。我知道成对函数的速度很慢(它是n^2),我也有其他更快的方法(Barnes hutt为一个,它是n logn),但这超出了我在这个问题中所要求的范围

<> > C++代码几乎相同:

struct Body
{
public:
    double Mass;
    Vector Position;
    Vector Velocity;
    Vector Acceleration;

    void Pairwise(Body &b)
    {
        Vector dr = b.Position - this->Position;
        double r2 = dr.LengthSq();
        double r3i = 1 / (r2 * sqrt(r2));

        Vector da = r3i * dr;
        this->Acceleration += (b.Mass * da);
        b.Acceleration -= (this->Mass * da);
    }

    void Predict(double dt)
    {
        Velocity += (0.5 * dt) * Acceleration;
        Position += dt * Velocity;
    }

    void Correct(double dt)
    {
        Velocity += (0.5 * dt) * Acceleration;
        Acceleration.Clear();
    }
};

void Pairwise(Body *b, int n)
{
    for (int i = 0; i < n; i++)
        for (int j = i + 1; j < n; j++)
            b[i].Pairwise(b[j]);
}

void Predict(Body *b, int n, double dt)
{
    for (int i = 0; i < n; i++)
        b[i].Predict(dt);
}

void Correct(Body *b, int n, double dt)
{
    for (int i = 0; i < n; i++)
        b[i].Correct(dt);
}
结构体
{
公众:
双质量;
矢量位置;
矢量速度;
矢量加速度;
空位成对(主体和b)
{
向量dr=b.位置-此->位置;
双r2=dr.LengthSq();
双r3i=1/(r2*sqrt(r2));
向量da=r3i*dr;
此->加速度+=(b.质量*da);
b、 加速度-=(此->质量*da);
}
空隙预测(双dt)
{
速度+=(0.5*dt)*加速度;
位置+=dt*速度;
}
无效正确(双dt)
{
速度+=(0.5*dt)*加速度;
加速度。清除();
}
};
成对无效(主体*b,内部n)
{
对于(int i=0;i
主回路:

for (int s = 0; s < steps; s++)
{
    Predict(bodies, n, dt);
    Pairwise(bodies, n);
    Correct(bodies, n, dt);
}
for(int s=0;s

还有一个Vector类,它的工作原理与常规数学向量类似,为了简洁起见,我不包括它。

您需要与本机代码进行接口。您可以将其放入DLL和pinvoke中。好的,当你不经常转换并且界面很薄的时候。最灵活、最快速的解决方案是用C++/CLI语言编写ref类包装器。请看下面的介绍

最后但并非最不重要的一点是,您确实应该分析C代码。系数8是相当过分的。在你至少对它为什么这么慢有半个概念之前,不要开始这样做。你不想在C++代码中重新考虑原因,这会毁掉一周的工作。 小心错误的直觉。64位代码实际上并不快,它通常比x86代码慢一点。它有一堆额外的寄存器,非常好。但是所有指针的大小都是原来的两倍,而且cpu缓存也不会增加一倍。

最简单的方法是创建C++ ActiveX DLL。 然后您可以在C#项目中引用它们,VisualStudio将创建用于包装ActiveX COM对象的互操作

您可以使用互操作代码,如C#代码,而无需额外的包装代码

有关AciveX/C#的更多信息:


您有两种选择:p/Invoking和C++/CLI

p/调用

通过使用p/javek或平台调用,.NET(因此C语言)可以调用非托管代码(C++代码)。它可能有点压倒一切,但是绝对有可能让你的C代码调用到性能关键的C++代码。 一些MSDN链接可帮助您入门:

基本上,您将创建一个C++ DLL,它定义了您希望从C调用的所有非托管函数。然后,在C#中,您将使用
DllImportAttribute
将该函数导入C#

例如,您有一个C++项目,创建一个具有以下功能的MunKi.dLL:

extern "C" __declspec(dllexport) void FastMonkey();
然后在C#中定义如下:

class NativeMethods
{
    [DllImport("Monkey.dll", CallingConvention=CallingConvention.CDecl)]
    public static extern void FastMonkey();
}

您可以调用Cype中的C++函数,调用<代码> NATEVIEMEDSOD。 一些常见的问题和注意事项:

  • 花时间学习互操作封送。理解这一点将大大有助于创建正确的P/调用定义
  • 默认ca
    class NativeMethods
    {
        [DllImport("Monkey.dll", CallingConvention=CallingConvention.CDecl)]
        public static extern void FastMonkey();
    }
    
    Vector dr = b.Position - this.Position;
    ...
    Vector da = r3i * dr;
    this.Acceleration += (b.Mass * da);
    b.Acceleration -= (this.Mass * da);