Здравствуйте, criosray, Вы писали:
NBN>>Я молчу про измерение времени выполнения этого теста в секундах! И уж тем более однократное.
C>Что мне смотреть дизассемблером,
А ты не посмотрел, что это одна и та же функция?
C>если я вижу, что время выполнения ухудшилась?
Имел бы практический опыт — знал бы что синтетические тесты имею мало смысла, тем более в такой примитивной реализации.
C>Вам и господину IID надо поменьше заниматься теорией и по больше практикой, чтоб не писать такой чуши.
(С) Я матлибами занимался ещё до того как ты программировать начал
Здравствуйте, NikeByNike, Вы писали:
C>>Вам и господину IID надо поменьше заниматься теорией и по больше практикой, чтоб не писать такой чуши. NBN>(С) Я матлибами занимался ещё до того как ты программировать начал
Очень рад, что Вы не работаете в моей команде. Если человек не понимает элементарной оптимизации и называет это "упрощением вычислений с некорректными результатами" или с умным видом предлагает заменить abs на fabs, когда это не имеет ровным счетом никакой практической пользы.
Здравствуйте, criosray, Вы писали:
C>Очень рад, что Вы не работаете в моей команде.
Я тоже
C>Если человек не понимает элементарной оптимизации
Замещение фпу-шных abs логикой — была уместна лет 6-7 назад. Однако с тех пор оно стало антиоптимизацией.
C>и называет это "упрощением вычислений с некорректными результатами"
Ты читать-то сначала научись, а потом с мнением лезь
C>или с умным видом предлагает заменить abs на fabs
Ты уже о себе в третьем лице начал говорить?
C>когда это не имеет ровным счетом никакой практической пользы.
Ещё бы, грамотный программист знает, что с некоторых пор это одна и та же функция
C>
Ага, может прекратишь пургу гнать?
Здравствуйте, criosray, Вы писали:
C>Месье — теоретик? Доки эти я читал за долго до того, как Вы программированием занялись. И знаю всяко лучше Вашего, что этой оптимизации компиллятор не сделает. Не верите — проверьте и убедитесь.
раз ВАм практика интересна
вот ВАши слова:
Не справляется. Ни один компилятор не догадается, что Spiral будет возвращать true значительно чаще, чем Golova.
а теперь немного ассемблера, я уверен все в этой теме его знают
0. будем выключать инлайнер — -Ob0, чтобы легче искать нужные функции в листинге. кроме того, я убрал из листинга Wall() и Strokes() и return 0 и соответствующий код, будем сравнивать Spiral и Golova
1. простой случай
icl -fast -Qopenmp -FAs -Ob0 test.cpp
?GetColor@Aux@@QAEIXZ PROC NEAR PRIVATE
.B2.1: ; Preds .B2.0
;;; {
push ebx ;52.5
sub esp, 8 ;52.5
mov ebx, ecx ;52.5
;;; if ( Golova() ) return 1;
call ?Golova@Aux@@QAE_NXZ ;53.14
; LOE eax ebx ebp esi edi
.B2.12: ; Preds .B2.1
movzx eax, al ;53.14
test eax, eax ;53.14
je .B2.3 ; Prob 43% ;53.14
; LOE ebx ebp esi edi
.B2.2: ; Preds .B2.12
mov eax, 1 ;53.32
add esp, 8 ;53.32
pop ebx ;53.32
ret ;53.32
; LOE
.B2.3: ; Preds .B2.12
;;; if ( Spiral() ) return 2;
mov ecx, ebx ;54.14
call ?Spiral@Aux@@QAE_NXZ ;54.14
; LOE eax ebx ebp esi edi
.B2.13: ; Preds .B2.3
movzx eax, al ;54.14
test eax, eax ;54.14
je .B2.5 ; Prob 43% ;54.14
; LOE ebx ebp esi edi
.B2.4: ; Preds .B2.13
mov eax, 2 ;54.32
add esp, 8 ;54.32
pop ebx ;54.32
ret ;54.32
прошу обратить внимание на комментарий компилятора "Prob 43%", означающий как раз вероятность того что вызов Golova() или Spiral() вернул false.
В примере выше вероятность в обоих случаях 43%, то есть компилятор действительно не знает какой вызов что чаще возвращает.
а теперь перейдем к другим баранам, а точнее к упомянутой profile guided optimization:
?GetColor@Aux@@QAEIXZ PROC NEAR PRIVATE
; parameter 1: ecx
.B2.1: ; 897169792 ; Preds .B2.0
;;; {
push edi ;52.5
sub esp, 8 ;52.5
mov edi, ecx ;52.5
;;; if ( Golova() ) return 1;
call ?Golova@Aux@@QAE_NXZ ;53.14
; LOE eax ebx ebp esi edi
.B2.12: ; 897169792 ; Preds .B2.1
movzx eax, al ;53.14
test eax, eax ;53.14
jne .B2.9 ; Prob 16% ;53.14
; LOE ebx ebp esi edi
.B2.2: ; 750015232 ; Preds .B2.12
;;; if ( Spiral() ) return 2;
mov ecx, edi ;54.14
call ?Spiral@Aux@@QAE_NXZ ;54.14
; LOE eax ebx ebp esi edi
.B2.13: ; 750015232 ; Preds .B2.2
movzx eax, al ;54.14
test eax, eax ;54.14
jne .B2.8 ; Prob 21% ;54.14
; LOE ebx ebp esi edi
.B2.3: ; 592994496 ; Preds .B2.13
Оп-па! Вот тут уже интересней — вероятности уже другие! Причем разные. То есть:
а) компилятор знает какая функция вызывается чаще
б) что она чаще возвращает
и таки да, Spiral возвращает true чаще, чем Golova
количество вызовов функций Golova(), Spiral() и т.д., полученное из данных профилировки — можно посмотреть в optimization report (-Qopt-report и сопутствующие ключики) и убедится, что компилятор это знает.
Теперь про оптимизацию. Заметили, что в первом примере использовалась команда je, а во втором jne? вот это она и есть, оптимизация (до перестановки вызовов не дошло кстати). компилятор, сообразив что скорее всего получит false, решил поставить jne, в таком случае наиболее вероятно что переход не произойдёт (не будет сразу же выполнен return 4/3/2/1, а пойдет звать другие функции) и не будет сброса конвейера.
Всё это прямо противоречит твоему утверждению, которое я процитировал в начале этого сообщения.
Здравствуйте, IID, Вы писали:
IID>Здравствуйте, Antikrot, Вы писали:
A>>было бы еще интересно на кваде проверить опенмпишный вариант
IID>Вечером заценю на домашнем Q6600. И опенмпшный, и сишарповский
Честно попытался запустить C# вариант с Parallel.For, но замучался. По дефолту 2008-ая этого не умеет. Скачал и установил ParallelExtensions_Jun08CTP.msi Всё равно неймспейс System.Threading.Concurrency, как и System.Concurrency неизвестен. А т.к. в шарпе я не большой спец — забил.
Так что время исполнения C# кода пока остаётся тем же, и мы уже имеем 1353% преимущества.
Здравствуйте, IID, Вы писали:
IID>Честно попытался запустить C# вариант с Parallel.For, но замучался. По дефолту 2008-ая этого не умеет. Скачал и установил ParallelExtensions_Jun08CTP.msi Всё равно неймспейс System.Threading.Concurrency, как и System.Concurrency неизвестен. А т.к. в шарпе я не большой спец — забил. IID>Так что время исполнения C# кода пока остаётся тем же, и мы уже имеем 1353% преимущества.
Как-то нечестно, не находишь?
отлично, все как надо. абсолютно масштабируемая программа (итерации внешнего цикла-то независимые)
у меня было 18 с чем-то секунд на 2х ядрах по 2.4GHz, у тебя 9 на четырех таких же
IID>Так что время исполнения C# кода пока остаётся тем же, и мы уже имеем 1353% преимущества.
видел бы это Шеридан
Здравствуйте, MxKazan, Вы писали:
MK>Здравствуйте, IID, Вы писали:
IID>>Честно попытался запустить C# вариант с Parallel.For, но замучался. По дефолту 2008-ая этого не умеет. Скачал и установил ParallelExtensions_Jun08CTP.msi Всё равно неймспейс System.Threading.Concurrency, как и System.Concurrency неизвестен. А т.к. в шарпе я не большой спец — забил. IID>>Так что время исполнения C# кода пока остаётся тем же, и мы уже имеем 1353% преимущества. MK>Как-то нечестно, не находишь?
Расскажите как этот CTP включить — замеряю. Да и юзать CTP ещё более нечестно, вообще-то. В intel'e что openmp что GPO не являются tech preview фичами.
Здравствуйте, IID, Вы писали:
IID>Расскажите как этот CTP включить — замеряю.
Reference на сборки то добавил? В любом случае раз не можешь замерить, так и не нужно делать выводы.
Здравствуйте, MxKazan, Вы писали:
MK>Здравствуйте, IID, Вы писали:
IID>>Расскажите как этот CTP включить — замеряю. MK>Reference на сборки то добавил?
делаю Add Reference на проекте. На вкладке .NET громадный список сборок(?). Ничего похожего на ParallelExtensions/TPL/PLINQ там нет. ЧЯДНТ ? Желательно понятным языком расписать и по шагам.
MK>В любом случае раз не можешь замерить, так и не нужно делать выводы.
Это не штатная фича .NET платформы. Измерять её уже сомнительная затея. Но я готов идти навстречу.
Здравствуйте, IID, Вы писали:
IID>>>Расскажите как этот CTP включить — замеряю. MK>>Reference на сборки то добавил? IID>делаю Add Reference на проекте. На вкладке .NET громадный список сборок(?). Ничего похожего на ParallelExtensions/TPL/PLINQ там нет. ЧЯДНТ ? Желательно понятным языком расписать и по шагам.
Сборка называется System.Threading
MK>>В любом случае раз не можешь замерить, так и не нужно делать выводы. IID>Это не штатная фича .NET платформы. Измерять её уже сомнительная затея. Но я готов идти навстречу.
Это штатная фича дотнет начиная с 4.0. А пока можно скачать абсолютно рабочий CTP.
IID>>>Честно попытался запустить C# вариант с Parallel.For, но замучался. По дефолту 2008-ая этого не умеет. Скачал и установил ParallelExtensions_Jun08CTP.msi Всё равно неймспейс System.Threading.Concurrency, как и System.Concurrency неизвестен. А т.к. в шарпе я не большой спец — забил. IID>>>Так что время исполнения C# кода пока остаётся тем же, и мы уже имеем 1353% преимущества. MK>>Как-то нечестно, не находишь?
IID>Расскажите как этот CTP включить — замеряю. Да и юзать CTP ещё более нечестно, вообще-то. В intel'e что openmp что GPO не являются tech preview фичами.
Честно-нечестно... что за детский сад? У нас ParallelFx успешно применяется в одном из последних проектов.
Здравствуйте, IID, Вы писали:
IID>Честно попытался запустить C# вариант с Parallel.For, но замучался. По дефолту 2008-ая этого не умеет. Скачал и установил ParallelExtensions_Jun08CTP.msi Всё равно неймспейс System.Threading.Concurrency, как и System.Concurrency неизвестен. А т.к. в шарпе я не большой спец — забил.
IID>Так что время исполнения C# кода пока остаётся тем же, и мы уже имеем 1353% преимущества.
У Вас туго с арифметикой?
На двух ядрах дотнет вариант отрабатывает за 35 сек. Соответственно на 4х будет не больше 20 сек — то есть 100% от силы.
Здравствуйте, IID, Вы писали:
IID>>>Расскажите как этот CTP включить — замеряю. MK>>Reference на сборки то добавил? IID>делаю Add Reference на проекте. На вкладке .NET громадный список сборок(?). Ничего похожего на ParallelExtensions/TPL/PLINQ там нет. ЧЯДНТ ? Желательно понятным языком расписать и по шагам.
Добавляешь Reference на System.Threading.dll
В коде юзаешь пространство имен System.Threading parallel extensions to .net framework 3.5
A>Оп-па! Вот тут уже интересней — вероятности уже другие! Причем разные. То есть: A>а) компилятор знает какая функция вызывается чаще A>б) что она чаще возвращает
A>и таки да, Spiral возвращает true чаще, чем Golova
Здравствуйте, criosray, Вы писали:
C>У Вас туго с арифметикой? C>На двух ядрах дотнет вариант отрабатывает за 35 сек. Соответственно на 4х будет не больше 20 сек — то есть 100% от силы.
Не, давай по нормальному сравнивать. В каком постинге написано про 35 сек и какой конфиг (железо) использовался?
Здравствуйте, criosray, Вы писали:
C>>>Ок, замечательно. А как в предыдущем тесте у Вас получился корректный результат без private(a)? Потрудитесь объяснить. A>>если нет возражений, вечером попробую объяснить (сейчас по уши в линуксе сижу) C>Какие могут быть возражения...
ок, попробую на словах предположить почему у меня все правильно получилось при неправильном в принципе коде. это только мое предположение, никак не претендующее на истину в последней инстанции. не сверялось ни с репортами компилятора, ни с ассемблерным кодом (точнее, с кодом сверял, очень похоже на моё предположение, но конкретно показать не могу — кода немало).
на самом деле, что у нас есть состояние объекта "а"? всего лишь три поля .x, .y и .z. причем .z всегда 0. остается два поля, GetColor внутри себя состояние объекта не меняет, стало быть загоняем перед внешним циклом a.x и a.y в регистры до конца цикла (то есть фактически они становятся локальными для потока; а потом вообще никуда не сохраняем), и совершенно пофигу, что там будут делать другие потоки — в наши регистры они не влезут (то есть один поток не поменяет объект "a" другому, и ничего делать private тут и не надо). но это всё очень зависит от оптимизатора, сделает лишние чтение/запись в память (например, регистров не хватило) — и всё, приплыли.
C>Что ж, неплохо. Выявили узкое место, собрали dll`ку, подцепили ее к менеджед проекту и все пучком.
+1, очень подходящая причина делать части проекта на разных языках, подкрепленная цифрами
Здравствуйте, MxKazan, Вы писали:
C>>У Вас туго с арифметикой? C>>На двух ядрах дотнет вариант отрабатывает за 35 сек. Соответственно на 4х будет не больше 20 сек — то есть 100% от силы. MK>Не, давай по нормальному сравнивать. В каком постинге написано про 35 сек и какой конфиг (железо) использовался?
В одном из моих конечно: http://rsdn.ru/forum/Default.aspx?mid=3397236&flat=0
A>на самом деле, что у нас есть состояние объекта "а"? всего лишь три поля .x, .y и .z. причем .z всегда 0. остается два поля, GetColor внутри себя состояние объекта не меняет, стало быть загоняем перед внешним циклом a.x и a.y в регистры до конца цикла (то есть фактически они становятся локальными для потока; а потом вообще никуда не сохраняем), и совершенно пофигу, что там будут делать другие потоки — в наши регистры они не влезут (то есть один поток не поменяет объект "a" другому, и ничего делать private тут и не надо). но это всё очень зависит от оптимизатора, сделает лишние чтение/запись в память (например, регистров не хватило) — и всё, приплыли.
И что, Вы запускаете и каждый раз выдает корректный результат?