Re[5]: С# vs C++, голые цифры
От: midcyber
Дата: 19.05.09 22:51
Оценка:
Здравствуйте, Хвост, Вы писали:

Х>надеюсь вы находитесь в трезвом уме и твёрдой памяти и понимаете разницу между "алгоритм был изменён человеком так что исключена его корректная работа" и "в целях оптимизации, код алгоритма не был сгенерирован компилятором"


Разницу между "ложью" и "ошибкой", ты хотел сказать? Ключи оптимизации не взялись из ниоткуда

Впрочем, поскольку "ошибки" исходного поста устранены в тестах criosray, мы имеем
C++ — 77 секунд
С# — 86 секунд

ЧТД
Re[6]: С# vs C++, голые цифры
От: Хвост  
Дата: 19.05.09 23:02
Оценка:
Здравствуйте, midcyber, Вы писали:

M>Здравствуйте, Хвост, Вы писали:


Х>>надеюсь вы находитесь в трезвом уме и твёрдой памяти и понимаете разницу между "алгоритм был изменён человеком так что исключена его корректная работа" и "в целях оптимизации, код алгоритма не был сгенерирован компилятором"


M>Разницу между "ложью" и "ошибкой", ты хотел сказать? Ключи оптимизации не взялись из ниоткуда


M>Впрочем, поскольку "ошибки" исходного поста устранены в тестах criosray, мы имеем

M>C++ — 77 секунд
M>С# — 86 секунд

M>ЧТД


ето показывает лишь то что MS-компилятор генерит не самый быстрый во вселенной код, кстати скомпилируйте С++ код не с оптимизацией по скорости и с оптимизацией по размеру кода (/O1 у MS-компилятора), результат кого-то удивит.

я думаю что Intel'овский компайлер ничего не выкинул, а честно фигачил 27 секунд бесцельные циклы, а то что он оказался в разы быстрее MS-компилятора — так ето и не удивительно, учитывая что он на порядок дольше компилит.
People write code, programming languages don't.
Re[4]: С# vs C++, голые цифры
От: landerhigh Пират http://www.blinnov.com
Дата: 20.05.09 05:59
Оценка:
Здравствуйте, criosray, Вы писали:

C>Здравствуйте, Sorantis, Вы писали:


L>>>Не "превосходство С++", а превоходство интеловского компилятора перед MS-овским jit-ом.

L>>>Для корректного сравнения компилируйте C++-код MS-компилятором и сравнивайте.

S>>ну я и говорю.

S>>3 секунды под МС компиллер.

Ключевые моменты выделены.
98 секунд на Коре Дуо 2.4

основное время, понятное дело — синус с косинусом.

 Aux a;
    time_t t1, t2;
    time(&t1);
    int b = 0;
    
    for(int i = 0; i < 100; i++)
    {
        a.z = 0;
        for(a.y = -1.5; a.y < 1.5; a.y += 0.001)
        {
            for(a.x = -1; a.x < 2; a.x += 0.001)
            {

                b += a.GetColor();
            }
        }

    }
    time(&t2);
    cout << "elapsed: " << difftime(t2, t1) << " seconds.; b = " << b << endl;
www.blinnov.com
Re: С# vs C++, голые цифры
От: NikeByNike Россия  
Дата: 20.05.09 06:13
Оценка:
Здравствуйте, IID, Вы писали:

А почему ты применил даблы, а не флоаты?
Нужно разобрать угил.
Re[2]: С# vs C++, голые цифры
От: IID Россия  
Дата: 20.05.09 07:05
Оценка:
Здравствуйте, NikeByNike, Вы писали:

NBN>Здравствуйте, IID, Вы писали:


NBN>А почему ты применил даблы, а не флоаты?


Потому что так было в оригинальном коде.
kalsarikännit
Re[4]: С# vs C++, голые цифры
От: criosray  
Дата: 20.05.09 08:14
Оценка: 2 (1) +1
Здравствуйте, criosray, Вы писали:

C>Здравствуйте, Хвост, Вы писали:


C>>>2) самое значимое — так как алгоритм явно элементарно параллелится, то раскидал его на все доступные (их два у меня) ядра процессора с помощью Parallel.For

Х>>а можно узнать результаты теста без Parallel.For? меня терзают смутные сомнения что вы преувеличили лёгкость распараллеливания алгоритма и он у вас просто некорректно работает.

C>Elapsed 00:01:26.8746531


C>86 секунд — то есть примерно на 10-12% медлененнее С++ варианта.


C>На счет Parallel.For Вы правы — работает некорректно. Каюсь, час ночи + спешка — преувеличил легкость распараллеливания.


C>Завтра на свежую голову посмотрю внимательнее как его распараллелить.


Распараллелил. Топорно и наверняка не оптимально, но нет времени на лучшее.

Результат

Elapsed 00:00:45.3581939 sec.
1813065000

Подсчитанно корректно. В полтора раза быстрее С++ варианта без параллелинга, как видим.

Код (как видим я создаю объекты на куче в цикле, что очень не рационально):

...
            Parallel.For(0, 100, i =>
                         {
                             var a = new Aux();
                             int b = 0;

                             for (a.y = -1.5; a.y < 1.5; a.y += 0.001)
                             {
                                 for (a.x = -1; a.x < 2; a.x += 0.001)
                                 {
                                     
                                     b += a.GetColor();
                                 }
                             }

                             spinlock.Enter();
                             x += b;
                             spinlock.Exit();
                         });

            stopWatch.Stop();

            Console.WriteLine("Elapsed {0} sec.", stopWatch.Elapsed);
            Console.WriteLine(x);
Re: С# vs C++, голые цифры
От: frogkiller Россия  
Дата: 20.05.09 08:18
Оценка:
Здравствуйте, IID, Вы писали:

IID>Я привёл код в компилябельное состояние. Вот C# вариант, а вот C++ вариант. Для компиляции использовалась MSVS2008 со всеми обновлениями.


А почему в плюсовом варианте используется си-шный abs() он же вроде как возвращает int. Или в stdfx.h включён ещё и <cmath>?
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[5]: С# vs C++, голые цифры
От: Antikrot  
Дата: 20.05.09 08:30
Оценка: 1 (1) +1
Здравствуйте, criosray, Вы писали:

C>Распараллелил. Топорно и наверняка не оптимально, но нет времени на лучшее.

C>Результат
C>Elapsed 00:00:45.3581939 sec.
C>1813065000
C>Подсчитанно корректно. В полтора раза быстрее С++ варианта без параллелинга, как видим.

ну, продолжим я сегодня выступаю на стороне C++
(cpu: core2 2.4GHz — T7700 два ядра ноутбук 32bit winxp)

изначальный тест показывает 0 секунд на icc (ровно той же версии что и у топикстартера)
(всё собираю из комстроки)

твой вариант с распечаткой результата:
icl -fast test.cpp

test.exe
elapsed: 32 seconds.
1813065000

мой вариант с openmp:

#pragma omp parallel for reduction(+:x)
    for(int i = 0; i < 100; i++)
    {
        a.z = 0;
        for(a.y = -1.5; a.y < 1.5; a.y += 0.001)
        {
            for(a.x = -1; a.x < 2; a.x += 0.001)
            {
                x += a.GetColor();
            }
        }

    }


icl -fast -Qopenmp test.cpp

запуск на два потока будет
test.exe
elapsed: 18 seconds.
1813065000

твой ход
Re[2]: С# vs C++, голые цифры
От: frogkiller Россия  
Дата: 20.05.09 08:56
Оценка:
Здравствуйте, frogkiller, Вы писали:

F>А почему в плюсовом варианте используется си-шный abs() он же вроде как возвращает int. Или в stdfx.h включён ещё и <cmath>?


Кстати, в указанном варианте со стандартным abs у меня даже и не скомпилялось, ругнулось на неопределённость перегрузки.

ЗЫ. На моей слабенькой машинке с линуксом и gcc замена <cmath> на <math.h> (и соответсвенно abs на fabs) сократило время работы в дебажной версии с 178 сек до 157 сек, т.е на 12%.
При -O2 времена составили, соответсвенно, 111 сек и 112 сек (т.е. с cmath даже быстрее)
При -O3 времена составили, соответсвенно, 111 сек и 111 сек.

Результат везде: 1813065000
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[6]: С# vs C++, голые цифры
От: criosray  
Дата: 20.05.09 09:37
Оценка:
Здравствуйте, Antikrot, Вы писали:

C>>Распараллелил. Топорно и наверняка не оптимально, но нет времени на лучшее.

C>>Результат
C>>Elapsed 00:00:45.3581939 sec.
C>>1813065000
C>>Подсчитанно корректно. В полтора раза быстрее С++ варианта без параллелинга, как видим.

A>ну, продолжим я сегодня выступаю на стороне C++

A>(cpu: core2 2.4GHz — T7700 два ядра ноутбук 32bit winxp)

A>изначальный тест показывает 0 секунд на icc (ровно той же версии что и у топикстартера)

A>(всё собираю из комстроки)

A>твой вариант с распечаткой результата:

A>icl -fast test.cpp

A>test.exe

A>elapsed: 32 seconds.
A>1813065000

A>мой вариант с openmp:


Хм, не понял, а каким образом лочится состояние объекта а в Вашем варианте?

A>
A>#pragma omp parallel for reduction(+:x)
A>    for(int i = 0; i < 100; i++)
A>    {
A>        a.z = 0;
A>        for(a.y = -1.5; a.y < 1.5; a.y += 0.001)
A>        {
A>            for(a.x = -1; a.x < 2; a.x += 0.001)
A>            {
A>                x += a.GetColor();
A>            }
A>        }

A>    }
A>
Re[7]: С# vs C++, голые цифры
От: frogkiller Россия  
Дата: 20.05.09 09:50
Оценка:
Здравствуйте, criosray, Вы писали:

A>>мой вариант с openmp:


A>>
A>>#pragma omp parallel for reduction(+:x)
A>>    for(int i = 0; i < 100; i++)
A>>    {
A>>        a.z = 0;
A>>        for(a.y = -1.5; a.y < 1.5; a.y += 0.001)
A>>        {
A>>            for(a.x = -1; a.x < 2; a.x += 0.001)
A>>            {
A>>                x += a.GetColor();
A>>            }
A>>        }

A>>    }
A>>


C>Хм, не понял, а каким образом лочится состояние объекта а в Вашем варианте?


А зачем его лочить? Во внутреннем цикле a.y не изменяется, можно спокойно запускать в нескольких потоках со всеим значением a.y, а потом собрать полученный результат в переменную x.

Интересно было посмотреть, что будет, если суммировать не в переменную на стеке, а в такой же член класса:
a.sum += a.GetColor();

А в сам класс добавить vtable, для запутывания, так сказать Сможет в этом случае компилятор понять, что a.sum так же будет аддитивной?
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[7]: С# vs C++, голые цифры
От: Antikrot  
Дата: 20.05.09 10:16
Оценка:
Здравствуйте, criosray, Вы писали:

C>Хм, не понял, а каким образом лочится состояние объекта а в Вашем варианте?


A>>
A>>#pragma omp parallel for reduction(+:x)
A>>    for(int i = 0; i < 100; i++)
A>>    {
A>>        a.z = 0;
A>>        for(a.y = -1.5; a.y < 1.5; a.y += 0.001)
A>>        {
A>>            for(a.x = -1; a.x < 2; a.x += 0.001)
A>>            {
A>>                x += a.GetColor();
A>>            }
A>>        }

A>>    }
A>>


не понял, состояние чего? переменной x? или a? x указан в reduction, так что это проблема openmp, уж позвольте опустить объяснение как оно внутри работает.
что касается a, раз ты его втащил в Parallel.For, так я его буду делать private
#pragma omp parallel for reduction(+:x) private(a)

так он будет свой для каждого потока, и ничего лочить не надо.
Re[8]: С# vs C++, голые цифры
От: criosray  
Дата: 20.05.09 10:23
Оценка:
Здравствуйте, Antikrot, Вы писали:

A>Здравствуйте, criosray, Вы писали:


C>>Хм, не понял, а каким образом лочится состояние объекта а в Вашем варианте?


A>>>
A>>>#pragma omp parallel for reduction(+:x)
A>>>    for(int i = 0; i < 100; i++)
A>>>    {
A>>>        a.z = 0;
A>>>        for(a.y = -1.5; a.y < 1.5; a.y += 0.001)
A>>>        {
A>>>            for(a.x = -1; a.x < 2; a.x += 0.001)
A>>>            {
A>>>                x += a.GetColor();
A>>>            }
A>>>        }

A>>>    }
A>>>


A>не понял, состояние чего? переменной x? или a?

Я не спрашивал про х. Про х я и так вижу, что там аналог Incremental.Add

A>что касается a, раз ты его втащил в Parallel.For, так я его буду делать private

A>
A>#pragma omp parallel for reduction(+:x) private(a)
A>

A>так он будет свой для каждого потока, и ничего лочить не надо.
Ок, замечательно. А как в предыдущем тесте у Вас получился корректный результат без private(a)? Потрудитесь объяснить. А заодно приведите замеры с исправленным кодом — где добавлено private(a).
Re[8]: С# vs C++, голые цифры
От: criosray  
Дата: 20.05.09 10:30
Оценка:
Здравствуйте, frogkiller, Вы писали:


A>>>мой вариант с openmp:


A>>>
A>>>#pragma omp parallel for reduction(+:x)
A>>>    for(int i = 0; i < 100; i++)
A>>>    {
A>>>        a.z = 0;
A>>>        for(a.y = -1.5; a.y < 1.5; a.y += 0.001)
A>>>        {
A>>>            for(a.x = -1; a.x < 2; a.x += 0.001)
A>>>            {
A>>>                x += a.GetColor();
A>>>            }
A>>>        }

A>>>    }
A>>>


C>>Хм, не понял, а каким образом лочится состояние объекта а в Вашем варианте?


F>А зачем его лочить? Во внутреннем цикле a.y не изменяется, можно спокойно запускать в нескольких потоках со всеим значением a.y, а потом собрать полученный результат в переменную x.


Потому, что параллелится внешний цикл.

Поток 1: вызывает a.GetColor со значениями a.y = -1.5, a.x = -1
Поток 1: Golova() возвращает false
Поток 1: предположим, Spiral() должен был бы вернуть true, но ДО того, как он будет вызван:
Поток 2 перезаписывае a.y и a.x соответствующими инкрементами!
Поток 1: Spiral() возвращает false и объект а теперь в таком состоянии, что только Golova вернула бы true — все проверки возвращают false, GetColor — возвращает 0.


F>Интересно было посмотреть, что будет, если суммировать не в переменную на стеке, а в такой же член класса:

F>
a.sum += a.GetColor();

F>А в сам класс добавить vtable, для запутывания, так сказать Сможет в этом случае компилятор понять, что a.sum так же будет аддитивной?
Хороший вопрос...
Re[9]: С# vs C++, голые цифры
От: Antikrot  
Дата: 20.05.09 10:54
Оценка:
Здравствуйте, criosray, Вы писали:

F>>Интересно было посмотреть, что будет, если суммировать не в переменную на стеке, а в такой же член класса:

F>>
a.sum += a.GetColor();

F>>А в сам класс добавить vtable, для запутывания, так сказать Сможет в этом случае компилятор понять, что a.sum так же будет аддитивной?
C>Хороший вопрос...
всё конечно интересно, но компилятор ничего не понимает, ему явно указано что аддитивное. да и указать a.sum в reduction как-то не получается...
лочить же a.sum += a.GetColor() с помощью omp critical сильно всё затормаживает (у меня почти в восемь раз)
Re[9]: С# vs C++, голые цифры
От: frogkiller Россия  
Дата: 20.05.09 10:54
Оценка:
Здравствуйте, criosray, Вы писали:


C>>>Хм, не понял, а каким образом лочится состояние объекта а в Вашем варианте?


F>>А зачем его лочить? Во внутреннем цикле a.y не изменяется, можно спокойно запускать в нескольких потоках со всеим значением a.y, а потом собрать полученный результат в переменную x.


C>Потому, что параллелится внешний цикл.


C>Поток 1: вызывает a.GetColor со значениями a.y = -1.5, a.x = -1

C>Поток 1: Golova() возвращает false
C>Поток 1: предположим, Spiral() должен был бы вернуть true, но ДО того, как он будет вызван:
C>Поток 2 перезаписывае a.y и a.x соответствующими инкрементами!
C>Поток 1: Spiral() возвращает false и объект а теперь в таком состоянии, что только Golova вернула бы true — все проверки возвращают false, GetColor — возвращает 0.

Это всё понятно. Я к тому, что нужно не лочить, а создавать копию. Более корректным было бы описать методы класса Aux как константные, но тут компилятор сам об этом догадался.


F>>Интересно было посмотреть, что будет, если суммировать не в переменную на стеке, а в такой же член класса:

F>>
a.sum += a.GetColor();

F>>А в сам класс добавить vtable, для запутывания, так сказать Сможет в этом случае компилятор понять, что a.sum так же будет аддитивной?
C>Хороший вопрос...

Подозреваю, что без помощи в виде явной спецификации константных методов не обойтись. Но проверить ме могу, под рукой только gcc, да и он не самый новый.
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[3]: С# vs C++, голые цифры
От: IID Россия  
Дата: 20.05.09 10:57
Оценка:
Здравствуйте, frogkiller, Вы писали:

F>ЗЫ. На моей слабенькой машинке с линуксом и gcc замена <cmath> на <math.h> (и соответсвенно abs на fabs) сократило время работы в дебажной версии с 178 сек до 157 сек, т.е на 12%.


Видимо библиотечная функция кривая... ABS в представлении с плавающей точкой это всего лишь безусловный сброс старшего бита, тормозить там (алгоритмически) нечему. Даже целочисленный ABS тормознее (условный NEG), если не реализован в железе.
kalsarikännit
Re[4]: С# vs C++, голые цифры
От: frogkiller Россия  
Дата: 20.05.09 11:05
Оценка:
Здравствуйте, IID, Вы писали:

IID>Здравствуйте, frogkiller, Вы писали:


F>>ЗЫ. На моей слабенькой машинке с линуксом и gcc замена <cmath> на <math.h> (и соответсвенно abs на fabs) сократило время работы в дебажной версии с 178 сек до 157 сек, т.е на 12%.


IID>Видимо библиотечная функция кривая... ABS в представлении с плавающей точкой это всего лишь безусловный сброс старшего бита, тормозить там (алгоритмически) нечему. Даже целочисленный ABS тормознее (условный NEG), если не реализован в железе.


Ну, помимо abs там ещё поменялись, очевидно, и всякие cos/sin
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[10]: С# vs C++, голые цифры
От: criosray  
Дата: 20.05.09 11:11
Оценка:
Здравствуйте, frogkiller, Вы писали:


F>Это всё понятно. Я к тому, что нужно не лочить, а создавать копию.

Да, я именно это подразумевал.

Еще десять минут на оптимизацию и с 45 сек уменьшил время до 32 сек:


        private bool Strokes()
        {
            return (Math.Abs(0.5 - x) < 0.02
                    || (x > 0.5 && Math.Abs(ZzzFunc()) < 0.005))
                   /* && !Spiral() && !Golova() */;
        }

        private bool Wall()
        {
            return x > 0.5 /* && !Strokes() && !Spiral() */;
        }

        public int GetColor()
        {
            if (Spiral())
            {
                return 2;
            }

            if (Golova())
            {
                return 1;
            }

            if (Strokes())
            {
                return 3;
            }

            if (Wall())
            {
                return 4;
            }
            
            return 0;
        }
Re[11]: С# vs C++, голые цифры
От: IID Россия  
Дата: 20.05.09 11:23
Оценка: :)
Здравствуйте, criosray, Вы писали:

C>Еще десять минут на оптимизацию и с 45 сек уменьшил время до 32 сек:



C>
C>        private bool Strokes()
C>        {
C>            return (Math.Abs(0.5 - x) < 0.02
C>                    || (x > 0.5 && Math.Abs(ZzzFunc()) < 0.005))
C>                   /* && !Spiral() && !Golova() */;
C>        }
C>


Это что ещё за самодеятельность ?

C>
C>        private bool Wall()
C>        {
C>            return x > 0.5 /* && !Strokes() && !Spiral() */;
C>        }
C>


и тут

C>
C>        public int GetColor()
C>        {
C>            if (Spiral())
C>            {
C>                return 2;
C>            }

...skip... 

C>            return 0;
C>        }
C>


А вот это — всегда пожалуйста. Только удивительно что компилятор C# такое не осиливает, если это правда дало какой-то выигрыш.
Попытки упростить вычисления не годятся. Мы ведь можем и поменять пределы изменения пары x,y. И "упрощённый" код станет давать неверные варианты. (В суть закомментированного лень вчитываться, но этот код явно влияет на результат)
kalsarikännit
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.