Программирование на C#

почему бы не сравнить быстродействие кода разных компиляторов скажем на банальной сортировке громадного массива чисел...

какие проблемы :)

Дельфи:
Код:
procedure QuickSort(var A: array of Integer);

  procedure Q1(var A: array of Integer; iLo, iHi: Integer);
  var
    Lo, Hi, Mid, T: Integer;
  begin
    Lo := iLo;
    Hi := iHi;
    Mid := A[(Lo + Hi) div 2];
    repeat
      while A[Lo] < Mid do Inc(Lo);
      while A[Hi] > Mid do Dec(Hi);
      if Lo <= Hi then
      begin
        T := A[Lo];
        A[Lo] := A[Hi];
        A[Hi] := T;
        Inc(Lo);
        Dec(Hi);
      end;
    until Lo > Hi;
    if Hi > iLo then Q1(A, iLo, Hi);
    if Lo < iHi then Q1(A, Lo, iHi);
  end;

begin
  Q1(A, Low(A), High(A));
end;

procedure TThreadSortForm.Button1Click(Sender: TObject);
type
  PSortArray = ^TSortArray;
  TSortArray =  array[0..20000000] of Integer;
var
  i: Integer;
  T: DWORD;
  SortArray: PSortArray;
begin
  GetMem(SortArray, sizeof(TSortArray));
  T := GetTickCount();
  for I := Low(SortArray^) to High(SortArray^) do
      SortArray[I] := Random(500000);

  QuickSort(SortArray^);

  T := GetTickCount() - T;
  ShowMessage(IntToStr(T));
end;

Си-диез:
Код:
        private void Q1(int[] A, int iLo, int iHi)
        {
            int Lo = iLo;
            int Hi = iHi;
            int Mid = A[(Lo + Hi) / 2];
            do {
                while (A[Lo] < Mid)
                    Lo++;
                while (A[Hi] > Mid)
                    Hi--;
                if (Lo <= Hi)
                {
                    int T = A[Lo];
                    A[Lo] = A[Hi];
                    A[Hi] = T;
                    Lo++;
                    Hi--;
                }
            } while (Hi >= Lo);
            if (Hi > iLo)
                Q1(A, iLo, Hi);
            if (Lo < iHi)
                Q1(A, Lo, iHi);
        }

        private void QuickSort(int[] A, int max) 
        {
            Q1(A, 0, max);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            int n = 20000000;
            int[] A = new int[n];

            int T = Environment.TickCount;

            Random rnd = new Random();
            for (int i = 0; i < n; i++)
            {
                A[i] = rnd.Next(500000);
            }

            QuickSort(A, n-1);

            T = Environment.TickCount - T;
            MessageBox.Show(T.ToString());
        }

Результаты: 2594 против 4360мс. Думаю понятно, в чью пользу. Оптимизмруйте :)
 

gureedo

Самец :)
хм... а как ты замерял время выполнения?
на наручных часах? )
 
Ш

Штурман

1) Delphi 7, optimize+, debug-, ConsApp
GetTickCount() заменил на GetTime(). Runtime 4100~4300 ms

2) .NET(csc&clr от .NET 3.5), optimize+, debug-, ConsApp
Была проведена маленькая оптимизация. Runtime 4950~5250 ms.

Win SP2, процессор Pentium D какой-то на 2.8 ГГц.
25% это очень смешно... Delphi 7 хлам. Я готов заплатить и 100% производительности взамен нативности, эффективности и поддержки современных веб, winApp и датабейз технологий.
 
Ш

Штурман

хм... а как ты замерял время выполнения?
на наручных часах? )
В самой программе, вычисляется разница времени между двумя участками кода... это не совсем корректно, т.к. не учитывается статап... тогда бы Delphi выйграл еще папу ms.

Вечерком закатаю код и в ifc 10 с параллельными циклами и автоматическим распараллеливанием, раскручиванием и тд. Жди результатов))
 

Serge

Ословед
раз уж пошла гонка, то в шарпе при вызове функций параметры можно передавать по ссылке (ref), дабы не тратить время на создание временных объектов. особенно это касается гигантского массива с данными. вы два раза вызываете функцию передавая ей массив по значению, тем самым два раза выделяя память (и тратя на это время) на создание его временных копий. вроде бы так.

было бы неплохо уточнить: чем производилась сборка .Net кода? на каком фреймворке выполнялся код?
 
Ш

Штурман

раз уж пошла гонка, то в шарпе при вызове функций параметры можно передавать по ссылке (ref), дабы не тратить время на создание временных объектов. особенно это касается гигантского массива с данными. вы два раза вызываете функцию передавая ей массив по значению, тем самым два раза выделяя память (и тратя на это время) на создание его временных копий. вроде бы так.

было бы неплохо уточнить: чем производилась сборка .Net кода? на каком фреймворке выполнялся код?

1. Массив поумолчанию передается по ссылке
2. MSDN морит:
C# Programming Guide
Passing Arrays Using ref and out (C# Programming Guide)
A ref parameter of an array type may be altered as a result of the call.
Массив всегда передается по ссылке... и всегда его можно изменить))
Example 2
Если убрать ref, то вывод программы не измениться :)
 

URIEL

Ословед
1) Delphi 7, optimize+, debug-, ConsApp
GetTickCount() заменил на GetTime(). Runtime 4100~4300 ms

2) .NET(csc&clr от .NET 3.5), optimize+, debug-, ConsApp
Была проведена маленькая оптимизация. Runtime 4950~5250 ms.

Win SP2, процессор Pentium D какой-то на 2.8 ГГц.
25% это очень смешно... Delphi 7 хлам. Я готов заплатить и 100% производительности взамен нативности, эффективности и поддержки современных веб, winApp и датабейз технологий.
По поводу нативности хотелось бы пару слов сказать, раз уж зашла речь. .NET не единственная платформа для кроссплатформенной разработки, существуют ещё и различные фрэймворки типа gtk, Qt и wxWidgets.
Любопытства ради, скопмилировал данный код на C# под Mono. Результат - в среднем 5 секунд.
Дальше - больше. Сделал косметическую обработку кода, переведя его на C++/Qt. Собрал под линуксом G++ - результат 11 секунд. Нет, я, конечно, знал, что там оптимизация очень плохая и всё такое, но чтобы вот так... Кросс-компилятором mingw32msvc (в репозитарии дебиана стандартно идёт) собрал exe и прогнал под VirtualBox'ом - 4 секунды. Напугали меня слегка результаты подобные. Даже не знаю, что с G++ не так. :)
 
Ш

Штурман

IFC 10.1.011 содержит ошибку :newconfus - если включен Check Routine Interfaces, то компилятор не компилирует мою программу.

итог в Realse + параллелизм, загрузка на оба ядра 30-50%... и у dotNET также. Runtime около 4200 - также как и делфи:fie1:. Под G95 тоже около 4200. Но все компиляторы используют разные rand-функции!... fortran бы может и выиграл, если бы irand() была PURE и у меня был бы C2D.

Код:
    program Console1
    
    USE IFPORT
    
    implicit none
    
    INTERFACE 
    
    SUBROUTINE QS(X)
       INTEGER(4) X
       DIMENSION X(0:20000000)  
    END SUBROUTINE QS
    
    RECURSIVE SUBROUTINE Q1(M,iLo,iHi)
        INTEGER M(0:20000000)
        INTEGER iLo, iHi
    END SUBROUTINE Q1
       
    END INTERFACE 
    

    INTEGER(4), DIMENSION(0:20000000) :: A   
    INTEGER(4) :: I
   
    REAL :: time_begin, time_end
    
    CALL CPU_TIME ( time_begin )

    DO I = 0, 20000000
        A(I) = irand()
    END DO
    
    CALL QS(A)

    CALL CPU_TIME ( time_end )

    PRINT *, (time_end - time_begin)*1000;
    
    end program Console1
 
    
    SUBROUTINE QS(X)
       INTEGER(4) X
       DIMENSION X(0:20000000)
       CALL Q1(X,0,20000000-1)    
    END SUBROUTINE QS
    
    RECURSIVE SUBROUTINE Q1(M,iLo,iHi)
        INTEGER M(0:20000000)
        INTEGER iLo, iHi
        INTEGER :: Lo , Hi, Mid 
        INTEGER :: T
        
        Lo = iLo
        Hi = iHi
        Mid = M((Lo + Hi) / 2)
        
        DO WHILE (M(Lo) < Mid) 
             Lo = Lo + 1
        END DO
        DO WHILE (M(Hi) > Mid) 
             Hi = Hi - 1
        END DO
        IF (Lo <= Hi) THEN
             T = M(Lo)
             M(Lo) = M(Hi)
             M(Hi) = T
             Lo = Lo + 1
             Hi = Hi - 1
        END IF
        DO WHILE (Hi >= Lo)
            DO WHILE (M(Lo) < Mid) 
                Lo = Lo + 1
            END DO
            DO WHILE (M(Hi) > Mid) 
                Hi = Hi - 1
            END DO
            IF (Lo <= Hi) THEN
                T = M(Lo)
                M(Lo) = M(Hi)
                M(Hi) = T
                Lo = Lo + 1
                Hi = Hi - 1
            END IF
       END DO
                
        IF (Hi > iLo) THEN
             CALL Q1(M, iLo, Hi)
        END IF


        IF (Lo < iHi) THEN
             CALL Q1(M, Lo, iHi)
        END IF         
            
    END SUBROUTINE Q1

У кого есть C2D запустите файлы плизз(раз 10 из cmd, т.к. сразу закрывается окно)... и скажите время:
 
Ш

Штурман

По поводу нативности хотелось бы пару слов сказать, раз уж зашла речь. .NET не единственная платформа для кроссплатформенной разработки, существуют ещё и различные фрэймворки типа gtk, Qt и wxWidgets.

.NET наиболее нативная для Win:)... кто программировал под .NET и Delphi for Win поймет)

прогнал под VirtualBox'ом - 4 секунды. Напугали меня слегка результаты подобные. Даже не знаю, что с G++ не так. :)

Может все дело в rand-функции... попытайся без сортировки все прогнать.

Надо еще через дженерики все переписат))
 
Ш

Штурман

В VS2008 есть профайлер :newconfus... для C# 87.8% было потрачено на сортировку)) MS время зря не теряли.
 

URIEL

Ословед
Может все дело в rand-функции... попытайся без сортировки все прогнать.
Любопытно, конечно, но правда. Дело было в том, что я вызывал не напрямую функцию rand(), а Qt'шную обёртку qsrand(), которая сделана как "Thread-safe version of the standard C++ rand() function.", что в данном контексте никуда не упиралось. Но отъедало это добрых 8 секунд, вместо 2-х стандартной.
После замены на встроенный эквивалент, G++ стал показывать 4600-4800ms. Но msvc всё равно лучше, даже под виртуальной машиной - 4100-4200.

В VS2008 есть профайлер :newconfus... для C# 87.8% было потрачено на сортировку)) MS время зря не теряли.
Для G++ 84-85%.
 
Ш

Штурман

Любопытно, конечно, но правда. Дело было в том, что я вызывал не напрямую функцию rand(), а Qt'шную обёртку qsrand(), которая сделана как "Thread-safe version of the standard C++ rand() function.", что в данном контексте никуда не упиралось. Но отъедало это добрых 8 секунд, вместо 2-х стандартной.
После замены на встроенный эквивалент, G++ стал показывать 4600-4800ms. Но msvc всё равно лучше, даже под виртуальной машиной - 4100-4200.

Стандартный, это который в стандарте отмечен как Example... т.е. линейный конгруэнтный метод. Так он вообще негодный. Думаю тест выбран неверный... надо ООП тест с чтение/записью на HDD и еще с чем-нибуть.
 

URIEL

Ословед
Да если уж так пошло, то проще не заморачиваться, а посмотреть тесты в интернете. Думаю, на объективность они претендовать всё-таки могут. А так придётся постараться, чтобы действительно сделать глобальный тест производительности. То есть туда надо и чтение/запись свойств класса прикручивать, и работу с HDD, а также самые разные вариации циклов, динамические вызовы виртуальных функций, подсистему выделения памяти, стандартную библиотеку функций и много ещё чего. А оно как-то лень. :)
 
Ш

Штурман


gprof?... если сравнивать с MSVS, то gprof "запорожец", а MSVS "мерседес".

Хотя хватить оффтопить))... C# конечно не самый быстрый язык, но достаточно пригодный для обычных Windows программ.
Я легко подключаю dll к своим C#-программа и наслаждаюсь мощью icc и ifc. Хотя скоро наверно откажусь от такого решения.
 

URIEL

Ословед
Да, gprof. Пожалуй, соглашусь. Если кто-то и пишет на определённом языке, то наверняка не просто так и на то есть какие-то причины, так что, мне кажется, в итоге всё равно все останутся при своём мнении. ;)
 
Ш

Штурман

Если кто-то и пишет на определённом языке, то наверняка не просто так и на то есть какие-то причины, так что, мне кажется, в итоге всё равно все останутся при своём мнении. ;)

Не смог удержать от оффтопа))... Основа для выбора языка это задача, а на втором месте любовь или нелюбовь программиста. Хотя я знаком с C# не более пол месяца, но мне этот язык понравился... я влюбился в его синтаксис с первого взгляда :) Самое большое впечатление на меня произвел IL assembler (с ildasm впридачу) и лаконичность C#... непоследнюю роль сыграла и VS, с ее неинтеллектуальным редактором. До этого я воспитывался на C и Fortran-е... так что чаще приходилось дробить числа, а не рисовать формы. После *(*(*a[])())[] в C, C# стал для меня глотком свежего воздуха.
 
А слышал ли кто про XNA Game Studio теперь программировать игры стало легче.

XNA Game Studio Express – это новый продукт от Microsoft предназначенный для разработки игр и ориентированный на студентов и разработчиков-любителей. XNA Game Studio основан на Visual C# express 2005 и позволяет разработчикам создавать игры как для Windows так и для Xbox 360. XNA Game Studio Express состоит из:

Более подробная информацыя:
http://www.xnadev.ru/index.php?option=com_content&task=view&id=59&Itemid=31
 
Сверху