Pull to refresh
28
0
Алексей @Priest512

Java-разработчик

Send message
То есть как? Насколько я помню, Task всегда выполняется в подобного рода потоках? Или же зависит от того, сохранят контекст или нет?
Ну, а планировщик разве не берет поток из пула потоков?
Ну то есть как, происходит проверка на выполнение задачи. Если она не выполнилась, то происходит процедура подписки о завершении задачи Task. Также в процедуре подписки участвует объект AwaitUnsafeOnCompleted, который реализует дополнительные возможности await, в том числе запоминание контекста синхронизации, который нужно будет восстановить при возобновлении. Этот метод планирует конечный автомат для перехода к следующему действию.И вот он как раз занимается задачами… А это подхватывает уже другой поток
Сейчас нет у меня под рукой той книги, в которой читал про создание отдельного потока) Возможно, что-то путаю, я уточню. Насчет async/await да, это всего лишь синтаксис, самое интересное делает компилятор и код, который он генерит, запускает задачу в потоке и ждет Task или Task<_Result_>, которые выполняются в пуле потоков)
А разве LINQ не создает отдельный поток при работе? A async/await передает код на выполнение в поток, который берется из пула потоков?
Ясно, просто из истории языка Kotlin читал, что при его создании, многие ругались на компанию, за то что они никак плагин под Scala не допилят)
Интересно, те кто минусуют, объясните, где я прокололся)
Тут с Вами согласен на все 100%. Тот же LINQ создает отдельно рабочий поток (без вашего ведома) и из последовательности делает выборку по определенному критерию (поэтому рекомендуется большие списки инициализировать в левой части). При этом имеет ленивую инициализацию, так что только дефолтные настройки уже не радуют. Затем тот же async/await, который компилятор за кулисами раскручивает до конечного автомата и создает дополнительные объекты для сохранения состояния метода и всех его переменных (а если у вас много локальных переменных в методе, это опять же память), а затем кидает выполнение асинхронного метода в фоновый поток (благо из пула берется), а потом ожидание выполнения с уведомлением через потоки ввода-вывода системы, число которых равно числу физических ядер процессора (Hyper-Thearing с его виртуальными ядрами не считается) — все это несомненно нагрузка на систему и приводит к постоянным аллокациям и нагрузкам на систему. А учитывая как .NET резервирует память, при помощи полигонов… То, что вы сейчас описали, несомненно нуждается в простых, но надежных методах без всякой «красивой» приблуды. Тут ему естественно делать нечего, поэтому я считаю, что необходимо знать чего стоит эта красота на самом деле. Поэтому часто сижу и читаю код, который генерит компилятор)))
Читал исходники SIMD-реализации в .NET, достаточно познавательно на самом деле.
Ну опять же, у Вас как я понимаю очень нагруженная система, соответственно специфические требования) В большинстве программ это удобно. Я вообще плюсы использую, когда мне нужна скорость, как у себя в проекте с математическими расчетами. Плюсы и быстрее и удобнее, хоть и требуют очень осторожного подхода) мелкие иногда ошибки, а память кушать начинает огромными темпами
Мм, интересно, что это у вас за проект такой)) Тут действительно, места ему нет, да и это может сказаться на работе кода. Однако, как я понимаю, это специфичный код. В большинстве случаев от сахара будет польза. К примеру работа с БД. Я как-то работал с MongoDB и там все обращения с выборкой и фильтрацией сделаны через LINQ, что очень удобно и быстро на самом деле. Если я захочу использовать, к примеру, SIMD-расширения в C#, то там код усложнится сразу, зато выше производительность. Или же еще взять то, что в Java в основном рекомендуется работать с интерфейсами, а не с конкретной реализацией, хотя такой подход дает нагрузку на JVM. Однако, на это особо не обращают внимания, так как такой подход позволяет писать удобный код.
Это сравнение чисто с точки зрения синтаксиса. Производительность тут не затрагивалась. Мне было интересно рассматривать этот язык, потому что он похож на С#. А как заметил мой коллега по работе, производительный код всегда тяжело читать. И как я вижу, иногда жертвуют производительностью ради хорошей читаемости и сопровождения кода. Я думаю, что грамотное использование синтаксического сахара позволит сделать код более приятным. Тот же С# в последних версиях имеет сахар, которым занимается компилятор, а сама платформа не изменяется.
Как бы посоветовали?
Насколько я знаю, есть плагин, который портирует код с Java на Kotlin.
Спасибо за столь полезную библиотеку! Когда завезете поддержку push-уведомлений? А то есть мысль сделать для себя простенький клиент.
Чтобы не было исключения, сборка должна быть релизной. На Debug у меня такая же ситуация.
Затем, как я выше упоминал, JIT сам выбирает какой SSE использовать или AVX. В вашем случае система выбрала AVX, а там 256-битный регистр. У вас соответственно больше элементов будет обрабатываться за один раз. В моем случае система выбрала SSE, там 128-битные регистры.
Я выше упоминал, что в С++ присутствует автоматическая векторизация. А вот компилятор C# не сделал бы этого ни при каких оптимизациях. Заранее сложный пример был приведен для того, чтобы подробнее объяснить принцип работы и управлением вручную, а затем как это сделано в C#. Статья больше ориентирована на .NET, С++ здесь как большой брат и исключительно в качестве примера базиса.
Поправка — суперскалярными


Насчет суперскалярных согласен, просто не хотел упоминать об этом конкретно, а сосредоточиться чисто на понятии скалярного процессора от векторного, и что производители CPU предпринимают для улучшения качества продукции.
Про выравнивание данных я выше писал, что компилятор может использовать инструкции для которых не требуется выравнивание данных: например, movups. Просто на мой взгляд выравнивание стоит делать, если есть возможность. В ссылках на статьи, в одной из которых упоминается про выравнивание, также рекомендуется делать это. По большей части это относится к тем, кто работает с неуправляемой памятью. Но в .NET я также видел ситуации, когда стоит делать выравнивание.
Про малые усилия, тут я имел ввиду, что для выполнения к примеру одного и того же алгоритма при помощи потоков или аппаратной поддержки, то в явном выигрыше аппаратная поддержка. Не нужно создавать потоки и управлять ими, меньше нагрузка на планировщик потоков и больше процессорного времени. Но при этом получаем равную или же даже лучшую производительность. Про использование аппаратных ресурсов, пусть даже только их узкое подмножество, то для .NET разработчиков это очень приятное дополнение. На плюсах векторизация была всегда, а на C# только появилась, что радует.
Для ARM есть технология SIMD, но тут она не поддерживается. Только x64. Я думаю под кросс-поддержкой имеется ввиду то, что происходит автоматический выбор SIMD-расширений, а в случае их отсутствия режим работы с обычной производительностью скалярного процессора.
Как видите, довольно много ограничений, но аппаратная поддержка в управляемом языке, это интересно.
SSE не полностью совместим с IEEE 754, поэтому результаты могут отличаться от скалярной версии

а вот про это можно поподробнее, где бы посоветовали почитать?
У первого видео автор очень хорошо рассказывает. Люблю его уроки смотреть, даже если знаешь, интересно узнавать новые моменты. При этом гоняюсь за уроками по виртуальной среде .NET, видел у него первый урок по этой тематике, но больше пока не находил.
Полностью согласен, особенно понравилось как в книге описан процесс выполнения асинхронных потоков с точки зрения выполнения программы. Т.е. он не ушел в описание потоков ОС и все связанное с их распределением, а рассмотрел все немного с другой позиции.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Registered
Activity