Я привёл код в компилябельное состояние. Вот C# вариант, а вот C++ вариант. Для компиляции использовалась MSVS2008 со всеми обновлениями.
— компилятор C# версии 3.5 Настроки релизной сборки — дефолтные. (Там-то и настраивать особо нечего).
— компилятор Intel С++ 11.0.072. Релизная сборка кастомизирована. Впрочем, разница между дефолтной релизной сборкой и кастомизированной невелика, порядка 10-15%. Ключи компиляции:
Тестовая машина: Intel Core2 Q6600, 800mhz RAM 8Gb. ОС — Windows 7 RC1 x64. Программы собирались для x86. Условия прогона: в диапазонах, указанных автором оригинального C# кода. Шаг по X/Y составляет 0.001 (всего за прогон обсчитывается 9млн пикселей). Делается 100(сто) прогонов подряд. Вычисляется суммарное время. Побочные эффекты: практически исключены. Сторонней нагрузки не было, taskmgr показывал загрузку только одного ядра во время прогонов. Т.е. гипотеза о том что интел компилер сумел заюзать несколько ядер отпадает.
С++ показал практически пятикратное преимущество (496%), обеспечив обсчёт ~33.33млн пикселей в секунду. C# осилил только ~6.71млн пикселей в секунду. (что довольно близко к результату автора в 5.9млн пикселей)
Итог: подавляющее превосходство С++. Не "немного быстрее", как утверждал автор, а в разы. Причём задача сводилась, фактически, только к грамотному распихиванию FPU команд. Интересно было бы посмотреть на работу с битами. Думаю, тут интел смог бы обеспечить ещё больший отрыв.
.
IID>Я привёл код в компилябельное состояние. Вот C# вариант, а вот C++ вариант. Для компиляции использовалась MSVS2008 со всеми обновлениями.
тест некорректен, результат вызова внутри циклов нигде не используется, компилятор мог там выкинуть что угодно (DCE, фигли, на таком-то уровне оптимизации да еще с проф-юзом), ограничившись парой вызовов time и cout<<
посему надо либо переделать, либо доказывай по асмовому коду что ничего не выкинуто
A>тест некорректен, результат вызова внутри циклов нигде не используется, компилятор мог там выкинуть что угодно (DCE, фигли, на таком-то уровне оптимизации да еще с проф-юзом), ограничившись парой вызовов time и cout<<
Тогда что он делал 27 секунд ?
A>посему надо либо переделать, либо доказывай по асмовому коду что ничего не выкинуто
Я, вообще-то в первоначальном топике так и предлагал — генерировать массивы чисел и проверять их на совпадение. Ок, аргумент уместен. Но это уже завтра.
Здравствуйте, IID, Вы писали:
A>>тест некорректен, результат вызова внутри циклов нигде не используется, компилятор мог там выкинуть что угодно (DCE, фигли, на таком-то уровне оптимизации да еще с проф-юзом), ограничившись парой вызовов time и cout<< IID>Тогда что он делал 27 секунд ?
ну, возможно, он выкинул *не всё*. но мне сейчас несподручно ставить нужную версию компилятора для проверки
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, IID, Вы писали:
IID>>Причём задача сводилась, фактически, только к грамотному распихиванию FPU команд.
AG>Вот именно. Посмотрим что С++ покажет, если задача будет сводится к поседовательности вызовов new
Давай C# вариант. Перепишем на С++ и поглядим. Есс-но аллокацию памяти я буду использовать такую, какую захочу.
.
IID>Я привёл код в компилябельное состояние. Вот C# вариант, а вот C++ вариант. Для компиляции использовалась MSVS2008 со всеми обновлениями. IID>- компилятор C# версии 3.5 Настроки релизной сборки — дефолтные. (Там-то и настраивать особо нечего). IID>- компилятор Intel С++ 11.0.072. Релизная сборка кастомизирована. Впрочем, разница между дефолтной релизной сборкой и кастомизированной невелика, порядка 10-15%. Ключи компиляции:
Во-первых, Вы понимаете, что это синтетическая числодробилка меряет не более, чем попугайчики?
Во-вторых, почему в С++ варианте у Вас floor, а в С# Math.Round(x,1) ?
Потратив десять минут на оптимизацию этого гения числодробильной мысли получил результат:
Elapsed 00:00:27.2390376 sec.
К сожалению на руках нет Intel С++ компиллятора, чтоб сравнить.
Код:
class Aux
{
public double x, y, z;
double ZzzFunc()
{
double xmy = x - y;
return xmy - Math.Floor(xmy);
}
double Spiral_()
{
double xk = x * 20;
const double a = 0.2;
const double b = 1.5;
double y1 = y * b - a * Math.Sin(xk);
double z1 = z * b - a * Math.Cos(xk);
return y1 * y1 + z1 * z1;
}
public bool Golova()
{
return x < 0.0 && x * x + y * y + z * z < 1.0 && !Shliz();
}
private bool Spiral()
{
return x > 0.0 && x < 1.75 && Math.Abs(Spiral_()) < 0.5;
}
private bool Shliz()
{
return x < -0.4 && y < 0.1 && y > -0.1;
}
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 (Golova()) return 1;
if (Spiral()) return 2;
if (Strokes()) return 3;
if (Wall()) return 4;
return 0;
}
};
class Program
{
static void Main(string[] args)
{
var a = new Aux();
var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();
Parallel.For(0, 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)
{
int c = a.GetColor();
}
}
});
stopWatch.Stop();
Console.WriteLine("Elapsed {0} sec.\n", stopWatch.Elapsed);
Console.ReadKey();
}
Что поменял:
1) сменил бредовое использование параметров во внутренних методах классов на использование полей класса;
2) заменил Math.Round на Math.Floor
2) самое значимое — так как алгоритм явно элементарно параллелится, то раскидал его на все доступные (их два у меня) ядра процессора с помощью Parallel.For
Вы скажете, что ах ну конечно я тоже мог бы использовать OpenMP и распаралеллить — могли, но не использовали.
Предпологаю, что у меня более быстрый процессор (Core2Duo 3GHz), чем у Вас, и что вариант на С++ отработал бы быстрее, чем за 27 секунд. Да. Но даже если бы он отработал в два раза быстрее (что сомнительно), все-равно мы видим, что "тормозной дотнет" на самом синтетичном и выигрышном для Intel C++ (самого мегаоптимизирующего С++ компиллятора с оптимизациями под Ваш процессор) тесте отстает-то в лучшем случае в два раза, а в худшем — так вообще ноздря в ноздрю.
Вот так "интерпретируемый язык" (с) Шеридан соперничает на числодробильном тесте с Intel C++
Здравствуйте, IID, Вы писали:
IID>Итог: подавляющее превосходство С++. Не "немного быстрее", как утверждал автор, а в разы. Причём задача сводилась, фактически, только к грамотному распихиванию FPU команд. Интересно было бы посмотреть на работу с битами. Думаю, тут интел смог бы обеспечить ещё больший отрыв.
Не "превосходство С++", а превоходство интеловского компилятора перед MS-овским jit-ом.
Для корректного сравнения компилируйте C++-код MS-компилятором и сравнивайте.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, IID, Вы писали:
IID>>Итог: подавляющее превосходство С++. Не "немного быстрее", как утверждал автор, а в разы. Причём задача сводилась, фактически, только к грамотному распихиванию FPU команд. Интересно было бы посмотреть на работу с битами. Думаю, тут интел смог бы обеспечить ещё больший отрыв.
L>Не "превосходство С++", а превоходство интеловского компилятора перед MS-овским jit-ом. L>Для корректного сравнения компилируйте C++-код MS-компилятором и сравнивайте.
Здравствуйте, criosray, Вы писали:
C>2) самое значимое — так как алгоритм явно элементарно параллелится, то раскидал его на все доступные (их два у меня) ядра процессора с помощью Parallel.For
а можно узнать результаты теста без Parallel.For? меня терзают смутные сомнения что вы преувеличили лёгкость распараллеливания алгоритма и он у вас просто некорректно работает.
Здравствуйте, Sorantis, Вы писали:
L>>Не "превосходство С++", а превоходство интеловского компилятора перед MS-овским jit-ом. L>>Для корректного сравнения компилируйте C++-код MS-компилятором и сравнивайте.
S>ну я и говорю. S>3 секунды под МС компиллер.
Потому что он умный и не станет гонять пустой цикл (а цикл пустой, т.к. результат расчетов нигде не используется, о чем, кстати, меня предупреждает среда Visual C#).
Если поменять код вот так, то получаем очень даже замечательный результат
int x = 0;
Parallel.For(0, 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();
}
}
});
Elapsed 00:00:28.1069964 sec.
int x = 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)
{
x += a.GetColor();
}
}
}
elapsed: 77 seconds.
Оба-на! Вот и приехали. Замечательный язык С++ не менее замечательно продул.
Уверен, что результат с OpenMP был бы на уровне шарпового, но проверить не могу — лень возиться и разбираться с OMP.
Здравствуйте, Хвост, Вы писали:
Х>Здравствуйте, criosray, Вы писали:
C>>2) самое значимое — так как алгоритм явно элементарно параллелится, то раскидал его на все доступные (их два у меня) ядра процессора с помощью Parallel.For Х>а можно узнать результаты теста без Parallel.For? меня терзают смутные сомнения что вы преувеличили лёгкость распараллеливания алгоритма и он у вас просто некорректно работает.
Ну если учесть, что C++ алгоритм из примера ВООБЩЕ не работает
Здравствуйте, midcyber, Вы писали:
M>Здравствуйте, Хвост, Вы писали:
Х>>Здравствуйте, criosray, Вы писали:
C>>>2) самое значимое — так как алгоритм явно элементарно параллелится, то раскидал его на все доступные (их два у меня) ядра процессора с помощью Parallel.For Х>>а можно узнать результаты теста без Parallel.For? меня терзают смутные сомнения что вы преувеличили лёгкость распараллеливания алгоритма и он у вас просто некорректно работает.
M>Ну если учесть, что C++ алгоритм из примера ВООБЩЕ не работает
Вобщем ветка создана потому что уж очень много страниц в предыдущей.
Ложный вызов товарищи
Здравствуйте, criosray, Вы писали:
C>Оба-на! Вот и приехали. Замечательный язык С++ не менее замечательно продул. C>Уверен, что результат с OpenMP был бы на уровне шарпового, но проверить не могу — лень возиться и разбираться с OMP.
распечай "х", чтобы убедиться что результат одинаковый. завтра буду уделывать с#
Здравствуйте, midcyber, Вы писали:
M>Ну если учесть, что C++ алгоритм из примера ВООБЩЕ не работает
надеюсь вы находитесь в трезвом уме и твёрдой памяти и понимаете разницу между "алгоритм был изменён человеком так что исключена его корректная работа" и "в целях оптимизации, код алгоритма не был сгенерирован компилятором"
Здравствуйте, Хвост, Вы писали:
C>>2) самое значимое — так как алгоритм явно элементарно параллелится, то раскидал его на все доступные (их два у меня) ядра процессора с помощью Parallel.For Х>а можно узнать результаты теста без Parallel.For? меня терзают смутные сомнения что вы преувеличили лёгкость распараллеливания алгоритма и он у вас просто некорректно работает.
Elapsed 00:01:26.8746531
86 секунд — то есть примерно на 10-12% медлененнее С++ варианта.
На счет Parallel.For Вы правы — работает некорректно. Каюсь, час ночи + спешка — преувеличил легкость распараллеливания.
Завтра на свежую голову посмотрю внимательнее как его распараллелить.