Когда я перестраиваю свою библиотеку c ++ DLL (которую я вызываю из c #) в / CLR (изначально нативный), производительность падает вдвое - PullRequest
1 голос
/ 24 марта 2019

Когда я изменил параметры сборки DLL с собственной на / CLR, чтобы я мог отлаживать через границу c # / c ++, моя производительность сократилась вдвое.

Я разработал собственную C ++ DLL с конкретными высокопроизводительными алгоритмами для решения своих вычислительных задач. Эту библиотеку DLL мне нужно было подключить к приложению C #, разработанному деловым партнером, и оно используется для замены алгоритма с более низкой производительностью. Все шло отлично, я подключил свою DLL, используя статические вызовы-обертки, алгоритм DLL работал отлично, показав увеличение производительности в 2 раза по сравнению с оригинальным алгоритмом, но не смог отладить через границу. Затем я переключил настройки сборки DLL c ++ с собственной на / CLR, чтобы иметь возможность отлаживать через границу DLL c # / c ++, и моя производительность упала вдвое.

Не могу понять, почему это так.

c ++ DLL сторона:

extern "C"
{
  __declspec(dllexport) void* NewCalc()
  {
    return (void*)new CalcCL;
  }
  __declspec(dllexport) double Calc(void* sCalc, int *Buf, int Cnt)
  {
    return ((CalcCl*)sCalc)->Calc(Buf, Cnt);
  }
}

c # сторона:

  [DllImport("CalcDLL.dll", CallingConvention = CallingConvention.Cdecl)]
  public static extern int NewCalc();
  [DllImport("CalcDLL.dll", CallingConvention = CallingConvention.Cdecl)]
  public static extern double Calc(int sCalc, int[] Buf, int Cnt);
...
  int sCalc = NewCalc();
...
  double res;
  int[] MyBuf = new int[1000];
  // <Code that fills MyBuf with target data for algorithm>
  res = Calc(sCalc, MyBuf, 1000);

1 Ответ

3 голосов
/ 24 марта 2019

С данным интерфейсом компиляция с / clr не дает никаких преимуществ.Сделайте отладочный собственный код C ++, щелкнув правой кнопкой мыши основной проект C #> Свойства> вкладка Отладка> отметив флажок «Включить отладку собственного кода».Это включает как управляемые, так и неуправляемые механизмы отладки.Вы не можете пошагово перейти к собственному коду, для выполнения изменения механизма отладки требуется точка останова на функции Calc ().Вы все еще можете предпочесть модульный тест, написанный на нативном C ++, если установка точек останова неудобна.

Еще одна вещь, о которой вам нужно позаботиться, это то, что вы создаете код C ++ с включенными настройками Debug.Вы получили это сейчас, поэтому код кажется в два раза медленнее.Проводите тестирование только с настройками Release build, чтобы убедиться, что оптимизатор включен.Лучше всего включить собственный проект C ++ в решение C #, чтобы вы всегда создавали правильный вариант.И вы должны убедиться, что правильная DLL скопирована в каталог сборки основного проекта C #, обычно это делается с событием после сборки.Этот шаг копирования должен отличаться для конфигураций Debug и Release.

Обратите внимание, что объявления [DllImport] являются неправильными.Тип возврата NewCalc () должен быть IntPtr, поэтому он также работает в 64-битном коде.Perf-тестирование 64-битной сборки кода C ++ - это то, что вы хотите попробовать, это может повысить производительность, если функция Calc () использует математику с плавающей запятой.На самом деле использование / clr может быть полезно для улучшения интерфейса, однако вы должны научиться писать код на C ++ / CLI и избегать сборки собственного кода C ++ с /clr.

.
...