1 | ||||||||||||||||
Оптимизация производительности C#.NET (Алгоритм, Многопоточность, Debug, Release, .Net Core, Net Native)26.03.2017, 13:39. Показов 4670. Ответов 19
Метки нет (Все метки)
Решил поделится своим небольшим опытом по оптимизации вычислений на C#.NET.
НЕ профи, палками не кидать, конструктив приветствуется! Тестом будет служить время вычисление всех переменных в заданном диапазоне (до 100000) в уравнении x^3 + y^3 = z^3 - 1 Симметричные решения по x и y не учитываем, т.е. из вариантов х=6,у=8,z=9 и х=8,у=6,z=9 - берем один (любой). Оборудование/Софт: Кликните здесь для просмотра всего текста
Тип ЦП QuadCore AMD Phenom II X4 Black Edition 955, 3200 MHz (16 x 200)
Системная плата Asus M4A89GTD Pro (2 PCI, 1 PCI-E x1, 1 PCI-E x4, 2 PCI-E x16, 4 DDR3 DIMM, Audio, Video, Gigabit LAN, IEEE-1394) Чипсет системной платы AMD 890GX, AMD K10 Системная память 8192 МБ (DDR3-1333 DDR3 SDRAM) Софт Win10x64, Excel2016x64, Visual Studio 2017 ШАГ1. Все кажется просто, берем и перебором ищем значения. Здесь сражу же упираемся в большое количество итераций - время выполнение неприлично большое. Поэтому ШАГ2 - Оптимизируем алгоритм, создаем массив из степеней Z, переберем значения х, у, обрезаем ненужные итерации, оставляем только один вариант x,y и обрезаем итерации на суммах x^3 + y^3 > z^3. Здесь (код) пальма первенства справедливо принадлежит m-ch - опять неприлично долго в VBA более 10 мин. ШАГ3. Берем этот алгоритм, переносим на C# и делим потоки, благо это задача хорошо бьется по потокам. Код (Сборка Debug x64): Кликните здесь для просмотра всего текста
Время выполнения чуть более 4 минут (по ссылке выше есть так же расчет и на Freebasic). Пока прохладно. ШАГ4. В C# (как проверено и не только в C#) расчет корня 3 степени медленнее, чем прямой перебор в массиве с некоторой хитростью (т.к. он отсортирован и перебор всегда ведется от меньшего к большему, или наоборот, легко запоминать последнюю найденную позицию и искать начиная с неё в след. цикле). Эта мысль меня посетила и была сразу реализована. Код (Сборка Debug x64) - делю на 4 потока, т.к. больше для моего ЦП -нет смысла: Кликните здесь для просмотра всего текста
Время выполнения - 41 сек. Уже теплее. ШАГ5. Как же я забыл про Release, срочно исправляюсь - Сборка Release x64. За счет оптимизации при компилировании получаем время выполнения - 17 секунд. Уже тепло. Появляются мысли про оптимизацию цикла (в сети множество советов и примеров), т.к. для вычисления требуется несколько миллиардов итераций. Думаю. ШАГ6. Почитав про .Net Core, решил попробовать. Новый проект - Консольное приложение .Net Core - вставляем предыдущий код и ... Время выполнения - 10,5 сек. Здесь мне кажется, что сделан максимум на C#. ШАГ7. Решил добить тему и погуглить. Есть интересный зверь net native, подробно писать здесь не буду. Кратко: В Windows 10 универсальные Windows-приложения на управляемых языках (C#, VB) проходят в магазине процедуру компиляции в машинный код с использованием .NET Native. Поэтому: создать проект-пустое приложение (универсальное приложение Windows)(UWP). Создаем button, textBox (на кнопку код, в textBox - переменные). Здесь нас поджидает проблемы с Threading. Переходим на Task, двигаем дальше. Код (Сборка Release x64) Кликните здесь для просмотра всего текста
Время выполнения 7,5 сек. Без вывода строки 5 сек.(подумать со строкой) ШАГ8. АССЕМБЛЕР... здесь мои знания заканчиваются... Что скажут ОТЦЫ, есть ли дальнейшая оптимизация? В блоге.
0
|
26.03.2017, 13:39 | |
Ответы с готовыми решениями:
19
Объясните на пальцах совместимость библиотек в .Net Core, .Net Framework, .Net Standart Разница между ASP.NET Core 2, ASP.NET Core MVC, ASP.NET MVC 5 и ASP.NET WEBAPI 2 Сравнение производительности MariaDb и PostgreSql на .NET CORE ASP.NET Core. Старт - что нужно знать, чтобы стать ASP.NET Core разработчиком? |
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
|
|||||||||||||||||||||
26.03.2017, 19:02 | 2 | ||||||||||||||||||||
bedvit, я не батька, поэтому напишу здесь.
В общем, проверил этот же код на своем компьютере, немного изменив, выдает следующие результаты: На 4 ядра: Код
1 8,419543 2 8,1585624 3 8,10069 4 8,4201469 5 8,0496835 6 8,1739722 7 8,2498671 8 8,323654 9 8,2459111 10 8,3008305 Код
1 5,7588025 2 5,9268395 3 5,6187675 4 5,6644015 5 5,6105386 6 5,6451581 7 5,6278141 8 5,7674422 9 5,7655258 10 5,7187006 Код
Затем решил поискать варианты с кодов, где реализован интерфейс TaskScheduler В итоге, вроде как, не чего не изменилось: Код
1 8,4415179 2 8,157661 3 8,3211735 4 8,280029 5 8,3083202 6 8,1099499 7 8,2338602 8 8,2312203 9 8,3099153 10 8,6700347 1 5,7908688 2 5,8020905 3 5,5635274 4 5,6112798 5 5,5907419 6 5,5647906 7 5,7027833 8 5,5974618 9 5,5683131 10 5,5568128 Код с TaskScheduler
Ну и на ресурсе itvdn есть свои примеры с реализацией этого интерфейса, но они выкидывают наллреференс, через раз =)) Проверил на 4 ядрах, на 8 не вышло без исключений. Код
1 8,5955904 2 7,9822086 3 8,434502 4 8,2540836 5 8,2939003 6 8,2409619 7 8,1733663 8 8,0794589 9 8,1387315 10 8,0360592 Код с классов с ресурсов itvdn
Еще один класс с itvdn
1
|
26.03.2017, 20:47 [ТС] | 3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Все возможные значения на текущем алгоритме (с int64). Отсортировано по Z. Итого 84 решения. Диапазон переменных 1:2097151((2^63)^(1/3)-1). См.под спойлер
Кликните здесь для просмотра всего текста
конфигурация та же, 4 ядра и т.д. (см. выше) Расчет по алгоритму ШАГ6 - 1час 29мин. По алгоритму ШАГ7 через (универсальное приложение Windows)(UWP) и компиляцию в машинный код, на таких больших диапазонах вылетает ошибка - причину пока не определил. Добавлено через 2 минуты А понять хочется ибо этот алгоритм/способ у меня самый быстрый сейчас. Добавлено через 3 минуты EveKS, насколько я понял, вы тоже через Console .Net Core, не через (универсальное приложение Windows)(UWP)?
0
|
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
|
||||||
27.03.2017, 08:41 | 4 | |||||
Не срастается...
Код
╨Ч╨░╨┤╨░╨╣╤В╨╡ ╨┤╨╕╨░╨┐╨░╨╖╨╛╨╜ ╤А╨░╤Б╤З╨╡╤В╨░ ╨┐╨╡╤А╨╡╨╝╨╡╨╜╨╜╤Л╤Е, ╨┤╨╛..., ╨╜╨░╨╢╨╝╨╕╤В╨╡ Enter: 100000 1 6 8 9 2 71 138 144 3 135 138 172 4 236 1207 1210 5 242 720 729 6 372 426 505 7 575 2292 2304 8 426 486 577 9 566 823 904 10 791 812 1010 11 1124 5610 5625 12 1851 8675 8703 13 1943 6702 6756 14 1943 11646 11664 15 1938 2820 3097 16 2196 5984 6081 17 2676 3230 3753 18 3086 21588 21609 19 3453 24965 24987 20 3318 16806 16849 21 4607 36840 36864 22 6560 59022 59049 23 7251 49409 49461 24 7676 11903 12884 25 8999 89970 90000 26 10230 37887 38134 27 10866 17328 18649 28 15218 66198 66465 29 17328 27630 29737 30 17384 78244 78529 31 25765 33857 38239 32 28182 31212 37513 33 29196 66167 68010 34 32882 69479 71852 35 31212 34566 41545 36 34199 46212 51762 37 51293 64165 73627 38 54101 56503 69709 39 58462 87383 95356 ╨Т╤А╨╡╨╝╤П ╨▓╤Л╤З╨╕╤Б╨╗╨╡╨╜╨╕╤П: 00:00:08.7553762 ╨Я╤А╨╛╨│╤А╨░╨╝╨╝╨░ ╨╖╨░╨▓╨╡╤А╤И╨╡╨╜╨░. ╨Э╨░╨╢╨╝╨╕╤В╨╡ Enter ╨┤╨╗╤П ╨▓╤Л╤Е╨╛╨┤╨░... bedvit, еще немного оптимизировал текущий алгоритм, ниже результат на 8 и 4 ядрах: Код
1 6,5317791 2 6,3221177 3 6,243117 4 6,2358343 5 6,2946634 6 6,4695762 7 6,1462388 8 6,4305404 9 6,3767552 10 6,4534968 1 4,4163211 2 3,9745174 3 3,9574649 4 3,9847986 5 4,017022 6 3,9952074 7 4,0651204 8 4,0272239 9 3,9591864 10 3,9934772 Код
Да верно. // ************* Нужно вкорне менять подход, т.к. переборы от 1 до нужного числа, не есть хороше. Возможно, стоит посмотреть в сторону деревьев или поискать другое решение. Не по теме: Вчерашний комент связан с недопониманием :)
0
|
27.03.2017, 11:59 [ТС] | 5 |
Срастается, потому как диапазон переменных взят больше - до 2097151. Вы и сами наверное уже поняли, судя по последнему коменту Это максимальное число для этого расчета/алгоритма.
Пока алгоритм сильно улучшить не удалось.
0
|
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
|
|||||||||||||||||||||||||||||||||||||||||
27.03.2017, 12:59 | 6 | ||||||||||||||||||||||||||||||||||||||||
bedvit, делать было нечего, решил дальше тестить, что да как:
Первые два варианта, вроде как дали маленький плюс, но не большой, выложу результаты на 4 ядра: 4 ядра, 2 варианта
Здесь я изменял только метод
Код
1 6,2182376 2 5,8958073 3 5,9115026 4 5,9840357 5 5,9454266 6 6,0558848 7 5,9110155 8 5,9936423 9 5,8191501 10 5,9548775
Код
1 6,0103062 2 5,9340868 3 6,0284483 4 5,974301 5 5,9692474 6 6,0021498 7 5,9640035 8 6,0357201 9 5,8541525 10 6,1153229
Но, в итоге, на данный момент, этот вариант выдает самые быстрые результаты, но с ошибкой в решении, и этому есть причина. Тесты на 8 и 4 ядрах: Код
1 5,7573051 2 5,5737364 3 5,6891549 4 5,6648332 5 5,60078 6 5,6390717 7 5,5251576 8 5,7240282 9 5,4985922 10 5,6186098 1 3,757608 2 3,5626847 3 3,4670908 4 3,4441495 5 3,4428092 6 3,4634318 7 3,4660047 8 3,5239459 9 3,6314177 10 3,4205503 Текущий код метода
Весь код
А теперь, о том об ошибке в вычислении: X всегда получается на 1 больше, чем нужно, из-за x++;. Y и Z верны(но всегда-ли это будет). Стоит убрать x++;, и решение становится верным, но время выполнения становится больше чем с x++; Результаты тестов без x++;
Код
1 6,3557662 2 6,2554463 3 6,0935981 4 6,0851149 5 6,2010127 6 6,2236964 7 5,9953513 8 6,1165849 9 6,0466032 10 6,3141701 1 4,5086063 2 3,9724535 3 4,0155356 4 3,9471268 5 3,9767078 6 3,9217126 7 3,9868509 8 4,0765498 9 3,9430604 10 3,9768568 И этого мало, казалось бы, если посмотреть весь код, то эту часть:
Но и тут нелепость, время выполнения становится дольше , т.е.: как не странно:
Результаты тестов с long x = start;
Код
1 6,1252225 2 5,9866461 3 5,9865261 4 5,9215376 5 6,0631918 6 6,0891908 7 6,0323686 8 5,8800278 9 5,9198172 10 6,0492911 1 4,2965829 2 3,9311391 3 3,9362909 4 3,9484388 5 4,2992103 6 3,9220456 7 4,1234166 8 3,9944103 9 3,9705379 10 3,966697
0
|
27.03.2017, 13:41 [ТС] | 7 |
EveKS, на первый взгляд странно. У вас не Win10 случаем? Хочу понять почему вариант/ШАГ7 не хочет работать на больших диапазонах переменных. Дело в компиляции или я чего-то не знаю/не учитываю. Пока у меня этот самый быстрый вариант за счет компиляции в машинный код (диапазон переменных до 500-600 тыс. далее вылетает ошибка). И да, спасибо за тесты!
0
|
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
|
|
27.03.2017, 14:00 | 8 |
0
|
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
|
||||||
27.03.2017, 14:40 | 9 | |||||
В алгоритм не вникал, но можно малость производительности выжать, если убрать проверку индексов массива:
Но надо, конечно, прогнать алгоритм через профайлер, чтобы быть точно уверенным.
2
|
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
|
|
27.03.2017, 15:45 | 10 |
kolorotur, интересно
Вот что выдает у меня на 4 и 8: Код
1 3,9415387 2 3,8029825 3 3,8341182 4 3,8432329 5 3,8694087 6 3,835299 7 3,8366115 8 3,8796129 9 3,8616481 10 3,8809787 1 2,2449393 2 2,4353302 3 2,3207624 4 2,2331703 5 2,1698065 6 2,1182683 7 2,1475558 8 2,1078534 9 2,1545005 10 2,2029385
0
|
28.03.2017, 11:43 [ТС] | 11 | ||||||||||||||||||||
уже лучше Кто сможеть протестить на win10 - создать проект-пустое приложение (универсальное приложение Windows)(UWP) - Relesex64 ? на работе win7 стоит. думаю на 30% прирост должен быть от текущего.
Добавлено через 3 часа 17 минут На рабочем ПК (4 потока)
Добавлено через 16 часов 3 минуты Прогнал дома код через .Net Native, ожидаемого прироста не получил. Разница небольшая от .Net Core
0
|
22 / 20 / 3
Регистрация: 12.10.2016
Сообщений: 62
|
|
28.03.2017, 13:11 | 12 |
Я думаю Вам стоит обратить внимание на выступления Андрея Акиньшина. Много хорошего подчерпнёте на тему перфоманса и, кстати, правильном способе его измерять. Потому что Ваш способ, конечно, не самый корректный
0
|
29.03.2017, 14:34 [ТС] | 13 |
За инфо Спасибо, глянем.
Добавлено через 22 часа 27 минут Развернул данное решение на .NET Core (.exe). Методика. Итого стандартный вариант на netcoreapp1.1, win7-x64 - 50 метров. Сокращенный вариант на netstandard1.6, win7-x64 - 30 метров. Плата за автономность (и некоторый прирост скорости по отношению к .NET Framework). Добавлено через 2 часа 22 минуты Выходит следующее(Тип ЦП (рабочий) QuadCore Intel Core i7-3770, 3700 MHz (37 x 100) - 8 лог.ядер): С#.NET Core - 2.0 сек. (скорость+, переносимость-) С#.NET Framework - 5,6 сек. (скорость-, переносимость+)
0
|
29.03.2017, 15:42 | 14 | |||||
Как измениться производительность, если вместо long z = 1; записать long z = x;?
Не нужно проверять весь массив с первого элемента, достаточно начинать с позиции x Добавлено через 4 минуты или
1
|
6452 / 4053 / 1599
Регистрация: 09.05.2015
Сообщений: 9,487
|
|
29.03.2017, 16:20 | 15 |
Это почему минус? .NET Core наоборот работает на гораздо большем количестве систем... И сборка .NET Core легко подключается к проектам на .NET Framework.
0
|
29.03.2017, 18:43 [ТС] | 16 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
m-ch, сейчас проверим, Someone007, согласен с тем, что не везде есть Framework, но под win проблем нет (а вот .NET Core есть точно не на всей win), поэтом что бы поделится своим решение на С#.NET Core нужно переслать - 50 МБайт(.exe+библиотеки), что бы С#.NET Framework - 50 КБайт(.exe)
Если не под Win, ситуация конечно меняется. Поправьте, если что-то упускаю. сможете поделится информацией? Тестовый код: Кликните здесь для просмотра всего текста
Добавлено через 5 минут z = (long)(x * 1.2599) выигрывает: Кликните здесь для просмотра всего текста
Добавлено через 30 минут С#.NET Framework догоняет С#.NET Core, разница всего в 5% Была поднята мин. граница массива в переборе, видимо С#.NET Core быстрее обрабатывает большие массивы. Кликните здесь для просмотра всего текста
0
|
31.03.2017, 14:07 [ТС] | 17 | ||||||||||
Подведя промежуточные итоги, последний вариант решения на .NETCoreApp1.1 (благодаря EveKS,kolorotur,m-ch).
Кликните здесь для просмотра всего текста
Решение на NET Framework 4.0 (макс. охват на win), здесь немного доработал свой код из стартового сообщения. Незначительно проигрывает Кликните здесь для просмотра всего текста
0
|
07.04.2017, 16:04 [ТС] | 20 |
Причем на более слабом ПК, разрыв увеличился до 20%. Видимо, CLR использует лучше более быстрые(?) ЦП (возможно оптимальнее использует инструкции(?) чем С++ скомпилированный под все х64)
0
|
07.04.2017, 16:04 | |
07.04.2017, 16:04 | |
Помогаю со студенческими работами здесь
20
Библиотека NETSquirrel для .NET и .NET Core - формат вывода индексаторов Можно ли использовать сборку из .NET Core в обычном ASP .NET проекте ? Можно ли использовать библиотеки написанные на .net Core для .net FW Как подключить к ConsoleApp(.Net Core) библиотеку (.Net Standart) Библиотека NETSquirrel для .NET и .NET Core - решение задач ASP.NET .NET Core Web Api -- почему параметры всегда null? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |