Организация безопасной удаленной работы с помощью решения Barracuda

Во время глобального кризиса, вызванного пандемией COVID-19 организациям необходимо быстро переводить сотрудников офиса на работу из дома.

ИТ-специалистам обеспечивающим возможность удаленной работы, необходимо найти надежные и безопасные способы связи домашних офисов с корпоративными приложениями. При этом они должны учесть возможность подключения на нескольких платформах, а также: обеспечить многофакторную аутентификацию, постоянную доступность на глобальном уровне, предотвращение несанкционированного доступа и применение политик безопасности.

Одно из решений, которое помогает справиться с этими задачами — Barracuda CloudGen Firewall c дополнительной опцией Расширенного безопасного удаленного доступа — аддоном доступным с версии F18 и выше. Решение можно развернуть как программно-аппаратный комплекс, виртуальный эпплаенс, а также как облачный инстанс в среде Amazon и Azure.

«Умные решения» для конечных точек

При условии использования add-on Barracuda Advanced Remote Access доступно несколько вариантов организации удаленного подключения к корпоративным ресурсам и приложениям:

  • Network-Access-Clients в разрезе VPN — организация VPN подключение для Windows, MacOS и Linux с производительностью и функционалом на порядок выше по сравнению со стандартным IPsec клиентским программным обеспечением.
  • Портал SSL-VPN предоставляет удаленным пользователям возможность доступа к корпоративным ресурсам путем перехода по URL ссылке и ввода их сетевых учетных данных. Этот вариант оптимален для организации доступа к ресурсам компании, независимо от местоположения пользователя или установленной операционной системы.
  • Приложение CudaLaunch предназначено для быстрого развертывания удаленного подключения на BYOD и мобильных устройствах. Доступно для Windows, macOS, iOS и Android.

Каждый межсетевой экран Barracuda CloudGen поддерживает неограниченное количество VPN-клиентов для базовых удаленных подключений, при этом дополнительных капиталовложений не требуется.

С чего начать?

Виртуальная триальная версия Barracuda CloudGen Firewall доступна для скачивания здесь, активна в течение 30 дней.

Как развернуть решение?

Процесс развертывание традиционных решений для удаленного подключения может быть сложным и требовать дополнительных затрат времени и ресурсов. Barracuda SSL VPN и клиенты CudaLaunch настраиваются самостоятельно и не требуют дополнительных ресурсов, кроме URL-адреса, необходимого для установления приложения и ввода учетных данных компании.

Приложение CudaLaunch доступно для скачивания в магазинах приложений для Microsoft, Google (Android) и Apple (macOS и iOS). Для полного прозрачного доступа к сети пользователь загружает и устанавливает VPN-клиент. Настройка VPN-клиентов производится автоматически после входа на SSL-VPN портал и загрузки автоматически сгенерированного файла конфигурации. Техническая документация с описанием пошагового процесса инсталляции решения доступна в открытом доступе.

Как применить политики безопасности для удаленных устройств?

Barracuda Network Access Client обеспечивает централизованное управление контролем доступа к сети и применение политик безопасности для удаленных сотрудников, подключенных к корпоративной сети.

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

Как оптимизируется полоса пропускания во время подключения большого количества сотрудников одновременно?

Организация удаленной работы для большого количества сотрудников одновременно может значительно снизить пропускную способность канала к сервису, а запрос на увеличение этого показателя сервис-провайдером может занять время и быть дорогостоящим. Решения удаленного доступа Barracuda CloudGen Firewall используют ультра-безопасный и надежный протокол сетевой архитектуры (TINA), который использует методы сжатия траффика, чтобы наилучшим образом использовать имеющуюся пропускную способность канала.

Где купить или получить консультацию

Компания Softprom – Value Added IT Distributor Barracuda Networks.

Узнать больше о вендоре Barracuda Networks на сайте ROI4CIO.

ссылка на оригинал статьи https://habr.com/ru/company/roi4cio/blog/525930/

Microsoft планирует крупное обновление пользовательского интерфейса Windows 10

В следующем году Microsoft хочет освежить пользовательский интерфейс Windows 10.

Источник: Microsoft
Источник: Microsoft
  • В 2021 году ожидается большое обновление пользовательского интерфейса для Windows 10;

  • Проект носит кодовое название «Sun Valley»;

  • Ожидаются улучшения в Проводнике, Пуске и режиме планшета.

Microsoft готовит крупное обновление ОС для Windows 10 в 2021 году, которое, по информации источников, принесет с собой значительное обновление дизайна пользовательского интерфейса Windows. Заку Баудэну (Zac Bowden) сообщили, что Microsoft планирует обновить многие элементы пользовательского интерфейса: меню «Пуск», Центр уведомлений и даже Проводник с использованием современного дизайна, улучшенной анимации и новых функций.

Проект пользовательского интерфейса имеет внутреннее название «Sun Valley» (Солнечная долина), и ожидается, что будет выпущен в рамках релиза Windows 10 «Cobalt» (Кобальт), запланированного на Рождественский сезон 2021 года. Внутренняя документация описывает проект как «оживление» и адаптацию опыта работы на Windows к современным требованиям, чтобы соответствовать ожиданиям клиентов в мире, управляемом другими современными и легкими платформами.

За последние пару лет Windows 10 оставалась почти такой же, практически не меняясь в дизайне или наборе предоставляемых функций. Многие другие платформы на рынке претерпели полный редизайн или обновление пользовательского интерфейса за последние пять лет. И, хотя Windows 10 претерпела незначительные изменения в дизайне с введением Fluent Design, мы не видели значительного обновления или переосмысления его пользовательского интерфейса.

Над проектом «Sun Valley», по-видимому, трудится команда «Windows Devices and Experiences» под руководством директора по продуктам Пэноса Паная, возглавивший указанное подразделение еще в феврале. В мае Microsoft объявила, что компания будет «реинвестировать» в Windows 10 в период до 2021 года, и источники Зака сообщают, что «Sun Valley» является результатом этого реинвестирования.

Чего же ожидать?

Источник: Windows Central
Источник: Windows Central

Еще слишком рано говорить о том, что именно будет обновлено касательно проекта «Sun Valley», но источники говорят, что следует ожидать появления нового меню «Пуск» и Центра уведомлений, вероятно, основанных на тех же функциях, что и в Windows 10X, но адаптированных для настольных компьютеров. Microsoft также работает над обновленной панелью задач, созданной с использованием обновленного кода, и улучшенным пользовательским интерфейсом для устаревшего проводника.

Что касается пользователей планшетов, Заку сообщили, что на подходе также улучшенная анимация и более плавная работа ОС. Мы уже знаем, что Microsoft перерабатывает сенсорную клавиатуру и средство выбора эмодзи, так как эти изменения уже представлены на канале «Dev» для инсайдеров. И Microsoft продолжит это «рискованное предприятие» скругления углов всего пользовательского интерфейса, включая окна приложений и другие области оболочки.

Источники также сообщают, что следует ожидать более широкого внедрения WinUI в оболочке Windows и встроенных приложениях, что даст едва различимые, но важные изменения в дизайне. Кроме того, ожидается, что больше областей классического пользовательского интерфейса получат поддержку темной темы, чтобы пользовательский интерфейс Windows выглядел и ощущался более согласованным.

Обновленный дизайн будет развитием Fluent Design, а не полным редизайном ОС. Microsoft не представляет новый язык дизайна с выходом «Sun Valley», а просто пытается обновить, переориентировать текущий язык на настольные системы и более последовательно применить его во всей ОС, что в общем-то является большим подвигом для устаревшего рабочего стола Windows.

Когда выход?

Источник: Windows Central
Источник: Windows Central

Важно подчеркнуть, что Microsoft может сократить или отложить релиз. Вероятно, что-то из запланированного не доведут до конечного продукта, поскольку такова природа разработки Windows и причина, по которой Microsoft не делает никаких анонсов заранее. Но это то, что Microsoft хочет предоставить клиентам Windows 10 в следующем году.

Microsoft надеется, что большая часть этой работы будет выполнена к концу семестра разработки «Cobalt», который завершится в июне 2021 года. Затем Microsoft подпишет RTM-версию билда, отправит ее OEM-производителям и начнет тестирование в бета-канале в качестве назначенного выпуска. Само обновление не станет общедоступным до осени, а скорее всего – с выходом LCU (последнее накопительное обновление) с последними функциями и исправлениями.

Если Microsoft удастся реализовать свои планы с Sun Valley, это будет крупнейшее обновление пользовательского интерфейса Windows 10, которое мы когда-либо видели до сих пор, после трех долгих лет, когда Windows 10 оставалась в стороне. Пэнос Панай хочет, чтобы люди перешли от необходимости в Windows к любви к ней. А современный, обновленный интерфейс, интуитивно понятный и ориентированный на дизайн, – это отличное начало.

С «Sun Valley» Windows 10 по-прежнему будет знакома пользователям ПК в отличие от перехода с Windows 7 на Windows 8. Заку также сообщили, что для некоторых функций можно будет переключаться между новым и старым интерфейсом, давая пользователям возможность выбора вместо принуждения. «Sun Valley» стремится улучшить и модернизировать привычный интерфейс Windows, а не радикально его изменить.

ссылка на оригинал статьи https://habr.com/ru/post/525826/

JAM-стэк — нищета на стероидах

Создавая сайты для малого бизнеса я сталкиваюсь с двумя крайностями. Но только я, как программист. Пользователи не сталкиваются, ведь нельзя столкнуться с тем чего для тебя не существует. Первая крайность — это когда клиент покупает за 50$ в месяц очередной хостинг для WordPress. Человек не знает, что для WordPress не нужен специальный хостинг, что такой специальный хостинг как правило хуже чем обычный хостинг и содержит кучу ограничений и стоит дороже. Вторая крайность — это когда используется JAM-стэк ради экономии. Но это экономия в плохом смысле этого слова, когда вы экономите на спичках, используя генератор для питания паяльника, от которого вы прикуриваете.

Говоря простым языком, JAM-стэк это куча костылей, использование которых выйдет боком всем, и прежде всего разработчику. Говоря техническим языком, JAM-стэк — это система интегрированных костылей для создания статических сайтов, с использованием SAAS для персистенции данных, а также значительной долей рендеринга на клиенте. Как делали статические сайты деды во времена своей молодости? Они писали простые HTML и CSS файлы и выкладывали их на хостинг по FTP. Как делали статические сайты наши отцы во времена своей буйной молодости? Они использовали Jekyll/Octopress, или любой из сотни генераторов статических сайтов, а полученные HTML и CSS файлы заливали на github pages через коммит, цепляли нужный домен. Некоторые тогда еще устраивали игрища с Disqus, потому что никак кроме игрищ я это назвать не могу, ведь пользователь с учёткой Disqus для оставления комментариев на вашем сайте исчезающе редок.

По балансу цена/затраты времени/сложность поддержки/ограничения в разработке это все было хорошим вариантом. Когда это переставало быть хорошим вариантом, покупался хостинг с php за пару баксов в месяц. Статические страницы ошаблонивались и обзаводились солидным функционалом полноценного сайта. И все было хорошо, а Енисей был из светлого пива. Но наши великие предки нашли нормальную работу и больше не страдают такой фигней. Теперь ей страдаем мы, и что же нам, молодым, смешливым, которым все легко, может предложить индустрия? Она гордо кровохаркает нам в лицо JAM-стэком, и говорит: «Не дождетесь!».

JAM-стэк — это новейший подход к созданию статических сайтов, и Gatsby.JS как один из пророков его. Gatsby — это самый яркий представитель жанра, возводящий насмешку над идеей статических сайтов в абсолют, переводя ее таким образом уже в разряд постиронии. Начнем с того, что Gatsby построен поверх React. Того самого React, который создавался для сайтов, где нужен компонентный подход, т.е. есть какие-то пользовательские интерфейсы, т.е. есть манипуляция с данными. Но у нас ведь статический сайт? Нет? Ретрограда ответ! Теперь это не проблема, у нас ведь есть сервисы типа Netlify и Contentful. Они предоставляют вам возможность через API делать AJAX запросы на их сервера и получать или записывать контент. Т.е. обычная база данных доступная через тридесятую задницу. Зато бесплатно. Первые N запросов, или пользователей, плюс лимит на размер блобов. Акция: уложись во все ограничения и получи оплату от заказчика* (*количество попыток ограничено).

Почему же на первый взгляд это выглядит привлекательно для бизнеса? Потому что React у всех на слуху, а Reactо-макак, которые еще вчера смогли войти в АйТи и готовых работать за копейки очень много. Для Reactо-макак это привлекательно потому что хоть какой-то способ поднять денег и набить портфолио. А сидя у мамки на шее можно литералли не платить ни за хостинг, ни за базу. По этой же причине сумневающемуся заказчику можно, увидев результат, прикинуть нужно ли оно ему вообще, и перестать отвечать на сообщения горе-фрилансера. Также заказчика и исполнителя объединяет достаточно малая компетентность, где первый не понимает как вообще все это работает, а второй не понимает, что сайты можно делать и по-другому.

В итоге, за редким исключением, о котором позже, проигрывают все. React и его производные это сложный инструмент с большой экосистемой и огромными проблемами, которые часто под силу только программистам на React, а не Reactо-макакам. 10 лет назад существовал популярный цирковой номер под названием «вытащить меню со всеми вложенными подменю за один SQL запрос». Теперь у нас есть его идейный наследник — вытащить все данные из нужного сервиса через один GraphQL запрос. Gatsby тянет за собой больше 500 зависимостей, и зная скорость обновления JS экосистемы можно смело сказать — через полгода что-то сломается, если вам понадобится новый сторонний виджет. Через 2 года вы будете заниматься черрипикингом версий, чтобы просто пересобрать это чудо в новый релиз. Да шучу я, шучу! Оно может и в первый раз не собраться по инструкциям с сайта. Если роскомнадзор в очередном порыве заботы о гражданах заблокирует ваш serverless database server, или просто сменит тариф, то развлекаться со всем этим опять вам. Кстати в отличие от традиционных статических сайтов билд сайта на Gatsby !== исходникам сайта. Так что стратегия бэкапа и развертывания этого чуда включая базу данных, да даже без неё, весьма занятная. Но самая мякотка начнется, если уродец созданный школьниками на кривых технологиях понадобится развивать. Поверьте, у PHP верхний предел ублюдочности legacy-кода гораздо ниже, что бы там про него не рассказывали!

Вам, как начинающему разработчику, JAM-стэк для коммерческих проектов использовать невыгодно. Во-первых, статик-сайты с минимальным функционалам — это самое дно фриланса со всем вытекающим и дурнопахнущим. Во-вторых, JAM-стэк — это прямая экономия на разработчике. Вы будете перерасходом своего времени компенсировать кривизну инструментов и сервисов, которая от вас не зависит и для борьбы с которыми у вас пока мало опыта. Тот что вы получите тут вам дальше не пригодится, потому что платежеспособные клиенты смогут вам оплатить хотя бы нормальный хостинг.

Так что же тогда подходящий случай для использования JAM-стэка в его современном виде? На мой взгляд, это ситуация когда ваш достаточно адекватный знакомый или родственник просит вас, React-программиста имеющего нормальную высокооплачиваему работу по своему профилю, сделать относительно простой сайт в свободное время. И вы используя существующие навыки сможете это быстро сделать, объяснив при этом человеку все недостатки такого подхода. И если он согласен, то тогда вперед. Иначе просто расскажите ему про WordPress и wp2static.

Критика и возражения приветствуются. Но будьте добры указать стоимость и количество проектов, которые вы сделали Gatsby, Next.

ссылка на оригинал статьи https://habr.com/ru/post/525910/

Про пользу E2E тестирования

В пирамиде тестирования End-to-End (E2E) тесты занимают одну из верхних ступеней. Написав один E2E тест, можно быть уверенным в результатах работы логики приложения, проверить интеграции с другими системами и создать «контракт» для вашего приложения.

К сожалению, многие из коллег, с которыми я работал, не писали E2E тесты. Отчасти потому что с головой ушли в модульное тестирование и посчитали, что оно лучше по ряду причин, включая моду на TDD. Отчасти потому что верили, что E2E тесты сложно писать, они долго исполняются, да и с инструментарием есть проблемы.

Разберемся с этими мнениями и посмотрим на плюсы, которые предлагает E2E тестирование.

Терминология

Под E2E тестами положим вид автотестов. Эти автотесты должны покрывать все функции сервиса с точки зрения клиента. Добиваются они этого, симулируя реальное взаимодействие клиента, будь это HTTP-запрос или нажатие на кнопку в UI.

Подход модульного тестирования лучше

Написание модульных тестов, к сожалению, занимает куда больше времени, чем E2E тестов. Да, на первых порах придется разобраться как E2E тесты лучше писать, но ведь то же было верно и для модульных тестов.

Зато, в результате один E2E тест покрывает больше кода, чем один Unit-тест, хотя может занимать меньшее количество строк по сравнению с аналогичным модульным test suite.

Можно не тратить время на понимание того, как правильно мокировать зависимости, ведь ими становяться в E2E тестах внешние системы, а взаимодействие с тестируемым сервисом строится по принципу «черного ящика».

Не нужно проверять все граничные условия для отдельного метода класса. Это повышает гибкость работы с кодом, так как нет необходимости рефакторить весь test suite при малейшем изменении внутренней логики работы приложения.

Невозможно попасть в ситуацию, когда ты боишься выкинуть старый код, потому что придется пройтись по набору из 100 модульных тестов (написанных даже не тобой), которые так или иначе были завязаны на этот код.

Инструментарий и скорость прогона тестов

На сегодняшний день большинство backend-разработчиков пишут сервисы, представляющие API с помощью HTTP (возможно GraphQL) или некоторым подобием MQ. В таком случае достаточно обычного клиента HTTP, доступного в большинстве mainstream ЯП.

Frontend-разработчики пишут, в основном, для Web-платформ (браузеров) или для мобильных в виде нативных приложений. Тут ситуация немного сложнее, так как инструментарий требует более детального изучения, но не дольше любого остального инструмента, с которым Вам придется столкнуться при разработке приложений.

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

Дополнительные плюсы E2E тестирования

Каждый отдельный тест покрывает реальный сценарий использования приложения и дает куда больше понимания другим разработчикам, в том числе и будущим, как именно и зачем все это работает.

По результатам работы Вы получаете «настоящий» code-coverage. Если есть код и его невозможно исполнить, выполняя клиентские запросы в реальном окружении, то, скорее всего, это лишний код. Если он проверяет граничные условия или ловит маловероятный exception, задумайтесь, возможны ли такие условия в принципе?

В целом, использование только E2E тестирования для приложения заставляет задуматься об упрощении структуры Вашей системы и улучшения документации.

E2E тесты могут использоваться как контракты API и взаимодействия с Вашим сервисом. К примеру, для backend, как только Ваш E2E тест меняется, необходимо убедиться, что frontend будет готов к таким изменениям.

Заключение

В целом, на мой взгляд, E2E тестирование предоставляет большие гарантии корректной работы системы, чем unit-тесты, большую гибкость в работе с кодом с точки зрения рефакторинга и отражает реальную суть работы приложения.

Спасибо Вам за внимание! А как Вы считаете, можно ли использовать только E2E тесты?

ссылка на оригинал статьи https://habr.com/ru/post/525934/

Сравнение времени выполнения алгоритма на CPU и GPU

Использование CUDA Runtime API для вычислений. Сравнение CPU и GPU вычислений

В данной статье я решил провести сравнение выполнения алгоритма написанного на C++ на центральном и графическом процессоре(выполнение вычислений с помощью Nvidia CUDA Runtime API на поддерживаемом GPU Nvidia). CUDA API позволяет выполнение некоторых вычислений на графическом процессоре. Файл c++ использующий cuda, будет иметь расширение .cu.
Схема работы алгоритма приведена ниже.

Задача алгоритма состоит в том, что найти возможные числа X, при возведении которых в степень degree_of, будет получатся исходное число max_number. Сразу отмечу, что все числа которые будут передаваться GPU, будут хранится в массивах. Алгоритм, выполняемый каждым потоком, имеет приблизительно следующий вид:

int degree_of=2; int degree_of_max=Number_degree_of_max[0];//Массив хранящий значение максимальной степени числа int x=thread;//номер выполняемого потока int max_number=INPUT[0];//Массив хранящий число, которое необходимо получить int Number=1; int Degree; bool BREAK=false;//Переменная для завершения while while(degree_of<=degree_of_max&&!BREAK){     Number=1;     for(int i=0;i<degree_of;i++){         Number*=x;         Degree=degree_of;     }     if(Number==max_number){         OUT_NUMBER[thread]=X;//OUT_NUMBER Массив хранящий числа которые необходимо возвести в степень Degree для получения исходного числа         OUT_DEGREE[thread]=Degree;// OUT_DEGREE Массив хранящий степень в которую нужно возвести число X для получения исходного числа     }    degree_of++;    //В случае выхода за предел : if(degree_of>degree_of_max||Number>max_number){     BREAK=true; } }  

Код для выполнения на CPU

#include <iostream> #include<vector> #include<string>//необходимо для getline #include<thread> #include<fstream> using namespace std; int Running_thread_counter = 0; void Upload_to_CPU(unsigned long long  *Number, unsigned long long  *Stepn, bool *Stop,unsigned long long  *INPUT, unsigned long long  *max, int THREAD); void Upload_to_CPU(unsigned long long  *Number, unsigned long long  *Stepn, bool *Stop,unsigned long long  *INPUT, unsigned long long  *max, int THREAD) { 	int thread = THREAD; 	Running_thread_counter++; 	unsigned long long  MAX_DEGREE_OF = max[0]; 	int X = thread; 	unsigned long long  Calculated_number = 1; 	unsigned long long  DEGREE_OF = 2; 	unsigned long long   INP = INPUT[0]; 	Stop[thread] = false; 	bool BREAK = false; 	if (X != 0 && X != 1) { 		while (!BREAK) { 			if (DEGREE_OF <= MAX_DEGREE_OF) { 				Calculated_number = 1; 				for (int counter = 0; counter < DEGREE_OF; counter++) { 					Calculated_number *= X; 				} 				if (Calculated_number == INP) { 					Stepn[thread] = DEGREE_OF; 					Number[thread] = X; 					Stop[thread] = true; 					BREAK = true; 				} 				DEGREE_OF++; 			} 			else { BREAK = true; } 		} 	} } void Parallelize_to_threads(unsigned long long  *Number, unsigned long long  *Stepn, bool *Stop,unsigned long long  *INPUT, unsigned long long  *max, int size); int main() { 	int size = 1000; 	unsigned long long  *Number = new unsigned long long[size], *Degree_of = new unsigned long long[size]; 	unsigned long long  *Max_Degree_of = new unsigned long long[1]; 	unsigned long long  *INPUT_NUMBER = new unsigned long long[1]; 	Max_Degree_of[0] = 7900;  	INPUT_NUMBER[0] = 216 * 216 * 216; 	ifstream inp("input.txt"); 	if (inp.is_open()) { 		string t; 		vector<unsigned long long>IN; 		while (getline(inp, t)) { 			IN.push_back(stol(t));  		} 		INPUT_NUMBER[0] = IN[0];//исходное число 		Max_Degree_of[0] = IN[1];//значение максимальной степени 	} 	else { 		ofstream error("error.txt"); 		if (error.is_open()) { 			error << "No file " << '"' << "input.txt" << '"' << endl; 			error << "Please , create a file" << '"' << "input.txt" << '"' << endl; 			error << "One read:input number" << endl; 			error << "Two read:input max stepen" << endl; 			error << "." << endl; 			error.close(); 			INPUT_NUMBER[0] = 1; 			Max_Degree_of[0] = 1; 		} 	} 	//расскометрируйте следующий код , если хотите видеть исходные значения в окне консоли  	//cout << INPUT[0] << endl; 	bool *Elements_that_need_to_stop = new bool[size]; 	Parallelize_to_threads(Number, Degree_of, Elements_that_need_to_stop, INPUT_NUMBER, Max_Degree_of, size); 	vector<unsigned long long>NUMBER, DEGREEOF; 	for (int i = 0; i < size; i++) { 		if (Elements_that_need_to_stop[i]) { 			if (Degree_of[i] < INPUT_NUMBER[0] && Number[i] < INPUT_NUMBER[0]) {//проверка на ошибки  				NUMBER.push_back(Number[i]); 				DEGREEOF.push_back(Degree_of[i]); 			} 		} 	} 	//расскометрируйте следующий код , если хотите вывести результаты в консоль 	//это может замедлить программу  	/* 	for (int f = 0; f < NUMBER.size(); f++) { 			cout << NUMBER[f] << "^" << DEGREEOF[f] << "=" << INPUT_NUMBER[0] << endl; 		} 		*/ 	ofstream out("out.txt"); 	if (out.is_open()) { 		for (int f = 0; f < NUMBER.size(); f++) { 			out << NUMBER[f] << "^" << DEGREEOF[f] << "=" << INPUT_NUMBER[0] << endl; 		} 		out.close(); 	} } void Parallelize_to_threads(unsigned long long  *Number, unsigned long long  *Stepn, bool *Stop,unsigned long long  *INPUT, unsigned long long  *max, int size) { 	thread *T = new thread[size]; 	Running_thread_counter = 0; 	for (int i = 0; i < size; i++) { 		T[i] = thread(Upload_to_CPU, Number, Stepn, Stop, INPUT, max, i); 		T[i].detach(); 	} 	while (Running_thread_counter < size - 1);//дождаться завершения выполнения всех потоков  } 

Для работы алгоритма необходим текстовый файл с исходным числом и максимальной степенью.

Код для выполнения вычислений на GPU

//библиотеки cuda_runtime.h и device_launch_parameters.h //для работы с cyda #include "cuda_runtime.h" #include "device_launch_parameters.h" #include<vector> #include<string>//для getline #include <stdio.h> #include<fstream> using namespace std; __global__ void Upload_to_GPU(unsigned long long  *Number,unsigned long long  *Stepn, bool *Stop,unsigned long long  *INPUT,unsigned long long  *max) { 	int thread = threadIdx.x; 	unsigned long long  MAX_DEGREE_OF = max[0];     int X = thread; 	unsigned long long  Calculated_number = 1; 	unsigned long long  Current_degree_of_number = 2;     unsigned long long   Original_numberP = INPUT[0]; 	Stop[thread] = false; 	bool BREAK = false; 	if (X!=0&&X!=1) { 		while (!BREAK) { 			if (Current_degree_of_number <= MAX_DEGREE_OF) { 				Calculated_number = 1; 				for (int counter = 0; counter < Current_degree_of_number; counter++) { 				 Calculated_number	*=X; 				} 				if (Calculated_number == Original_numberP) { 					Stepn[thread] = Current_degree_of_number; 					Number[thread] = X; 					Stop[thread] = true; 					BREAK = true; 				} 				Current_degree_of_number++; 			} 			else { BREAK = true; } 		} 	} } cudaError_t Configure_cuda(unsigned long long *Number, unsigned long long  *Stepn, bool *Stop,unsigned long long  *INPUT, unsigned long long  *max,unsigned int size); int main() { 	int size = 1000;     unsigned long long  *Number=new unsigned long long [size], *Degree_of=new unsigned long long [size]; 	unsigned long long  *Max_degree_of = new unsigned long long [1]; 	unsigned long long  *INPUT_NUMBER = new unsigned long long [1];    Max_degree_of[0] = 7900; 	 	 	ifstream inp("input.txt"); 	if (inp.is_open()) { 		string text; 		vector<unsigned long long>IN; 		while (getline(inp, text)) { 			IN.push_back( stol(text)); 				 		} 		INPUT_NUMBER[0] = IN[0]; 		Max_degree_of[0] = IN[1]; 	} 	else { 		ofstream error("error.txt"); 		if (error.is_open()) { 			error<<"No file "<<'"'<<"input.txt"<<'"'<<endl; 			error<<"Please , create a file" << '"' << "input.txt" << '"' << endl; 			error << "One read:input number" << endl; 			error << "Two read:input max stepen" << endl; 			error << "." << endl; 			error.close(); 			INPUT_NUMBER[0] = 1; 			Max_degree_of[0] = 1; 		} 	} 	 	 	bool *Elements_that_need_to_stop = new bool[size];     // Загрузка массивов в cuda 	cudaError_t cudaStatus =  Configure_cuda(Number, Degree_of, Elements_that_need_to_stop, INPUT_NUMBER, Max_degree_of, size);     if (cudaStatus != cudaSuccess) {         fprintf(stderr, "addWithCuda failed!");         return 1;     } 	vector<unsigned long long>NUMBER, DEGREEOF; 	for (int i = 0; i < size; i++) { 		if (Elements_that_need_to_stop[i]) { 			NUMBER.push_back(Number[i]);//занести в вектор число 			DEGREEOF.push_back(Degree_of[i]);//занести в вектор степень числа 		} 	} 	//раскоментируйте следующий код , чтобы вывести результаты в консоль 	/* 	for (int f = 0; f < NUMBER.size(); f++) { 		cout << NUMBER[f] << "^" << DEGREEOF[f] << "=" << INPUT_NUMBER[0] << endl; 	}*/ 	ofstream out("out.txt"); 	if (out.is_open()) { 		for (int f = 0; f < NUMBER.size(); f++) { 			out << NUMBER[f] << "^" << DEGREEOF[f] << "=" << INPUT_NUMBER[0] << endl; 		} 		out.close(); 	} 	     //Очистить ресурсы связанные с устройством     cudaStatus = cudaDeviceReset();     if (cudaStatus != cudaSuccess) {         fprintf(stderr, "cudaDeviceReset failed!");         return 1;     }      return 0; }   cudaError_t  Configure_cuda(unsigned long long  *Number, unsigned long long *Degree_of, bool *Stop,unsigned long long *INPUT, unsigned long long *max,unsigned int size) { 	unsigned long long *dev_Number = 0; 	unsigned long long *dev_Degree_of = 0; 	unsigned long long *dev_INPUT = 0; 	unsigned long long *dev_Max = 0; 	bool *dev_Elements_that_need_to_stop;  	cudaError_t cudaStatus;  	// УСТАНОВКА ИСПОЛЬЗУЕМОГО GPU  	cudaStatus = cudaSetDevice(0); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "cudaSetDevice failed!  Do you have a CUDA-capable GPU installed?"); 		goto Error; 	}  	// РЕЗЕРВИРОВАНИЕ МЕСТА В ПАМЯТИ ПОД ДАННЫЕ 	cudaStatus = cudaMalloc((void**)&dev_Number, size * sizeof(unsigned long long)); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "cudaMalloc failed!dev_Number"); 		goto Error; 	} 	cudaStatus = cudaMalloc((void**)&dev_Degree_of, size * sizeof(unsigned long long)); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "cudaMalloc failed!dev_Degree_of"); 		goto Error; 	} 	cudaStatus = cudaMalloc((void**)&dev_Max, size * sizeof(unsigned long long int)); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "cudaMalloc failed!dev_Max"); 		goto Error; 	} 	cudaStatus = cudaMalloc((void**)&dev_INPUT, size * sizeof(unsigned long long)); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "cudaMalloc failed!dev_INPUT"); 		goto Error; 	} 	cudaStatus = cudaMalloc((void**)&dev_Elements_that_need_to_stop, size * sizeof(bool)); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "cudaMalloc failed!dev_Stop"); 		goto Error; 	} 	// ПЕРЕМЕЩЕНИЕ ДАННЫХ В ПАМЯТЬ GPU 	cudaStatus = cudaMemcpy(dev_Max, max, size * sizeof(unsigned long long), cudaMemcpyHostToDevice); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "cudaMemcpy failed!"); 		goto Error; 	} 	cudaStatus = cudaMemcpy(dev_INPUT, INPUT, size * sizeof(unsigned long long), cudaMemcpyHostToDevice); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "cudaMemcpy failed!"); 		goto Error; 	} 	Upload_to_GPU<<<1, size>>>(dev_Number, dev_Degree_of, dev_Elements_that_need_to_stop, dev_INPUT, dev_Max); 	// Проверка сбоев ядра 	cudaStatus = cudaGetLastError(); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus)); 		goto Error; 	}  	// Ожидание завершения операций , выполняемых ядром  	cudaStatus = cudaDeviceSynchronize(); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus); 		goto Error; 	}  	// Перемещение данных из памяти GPU в системную память 	cudaStatus = cudaMemcpy(Number, dev_Number, size * sizeof(unsigned long long), cudaMemcpyDeviceToHost); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "cudaMemcpy failed!"); 		goto Error; 	} 	cudaStatus = cudaMemcpy(Degree_of, dev_Degree_of, size * sizeof(unsigned long long), cudaMemcpyDeviceToHost); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "cudaMemcpy failed!"); 		goto Error; 	} 	cudaStatus = cudaMemcpy(Stop, dev_Elements_that_need_to_stop, size * sizeof(bool), cudaMemcpyDeviceToHost); 	if (cudaStatus != cudaSuccess) { 		fprintf(stderr, "cudaMemcpy failed!"); 		goto Error; 	} Error://Освобождение памяти GPU от данных 	cudaFree(dev_INPUT); 	cudaFree(dev_Degree_of); 	cudaFree(dev_Max); 	cudaFree(dev_Elements_that_need_to_stop); 	cudaFree(dev_Number);  	return cudaStatus; } 

Идентификатор

__global__  

в .cu файле указывает, что функция выполняется на уровне ядра GPU.

Для работы с cyda, перед вызовом функции, нужно зарезервировать память под массив и перенести элементы в память GPU. Это увеличивает объем кода, но позволяет разгрузить CPU, так как вычисления производятся на GPU.Поэтому ,cuda, дает как минимум возможность разгрузить процессор для выполнения других нагрузок, не использующих cuda.

В случае примера на cuda, задача процессора заключается лишь в загрузке инструкций на GPU и обработке результатов пришедших с GPU; В то время как в коде для CPU, процессор обрабатывает каждый поток. Стоит отметить, что cyda имеет ограничения по количеству запускаемых потоков, поэтому в обоих алгоритмах я взял одинаковое количество потоков, равное 1000. Также, в случае с CPU я использовал переменную

int Running_thread_counter = 0;

чтобы считать количество уже выполненных потоков и дожидаться, пока все потоки не выполнятся.

Тестируемая конфигурация

  • CPU :amd ryzen 5 1400(4core,8thread)
  • ОЗУ:8гбDDR4 2666
  • GPU:Nvidia rtx 2060

  • OS:windows 10 version 2004
  • Cuda:
    • Compute Capability 7.5
    • Threads per Multiprocessor 1024
    • CUDA 11.1.70

  • GPU-Z:version 2.35.0
  • Visual Studio 2017

Сведения о cyda были взяты из GPU-Z

Для тестирования алгоритма я использовал

следующий код на C#

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; using System.IO; namespace ConsoleAppTESTSTEPEN_CPU_AND_GPU_ {     class Program     {         static string Upload(Int64 number,Int64 degree_of)         {             string OUT = "";             string[] Chord_values = new string[2];             Int64 Degree_of = degree_of;             Int64 Number = number;             Chord_values[0] = Number.ToString();             Chord_values[1] = Degree_of.ToString();             File.WriteAllLines("input.txt", Chord_values);//файл входных данных             OUT+="input number:" + Number.ToString()+"\n";             OUT+="input degree of number:" + Degree_of.ToString()+"\n";             DateTime running_CPU_application = DateTime.Now;//записать время запуска программы             Process proc=  Process.Start("ConsoleApplication29.exe");//exe реализация алгоритма на c++ x64 использующая CPU для вычислений             while (!proc.HasExited) ;//дождатся завершения программы             DateTime stop_CPU_application = DateTime.Now;//записать время остановки программы              string[]outs = File.ReadAllLines("out.txt");//получить результаты             File.Delete("out.txt");             OUT+="CPU:"+"\n";             if (outs.Length>0)             {                 for (int j = 0; j < outs.Length; j++)                 {                     OUT+=outs[j]+"\n";                 }             }             else { OUT+="no values"+"\n"; }             OUT+="running_CPU_application:" + running_CPU_application.ToString()+"\n";             OUT+="stop_CPU_application:" + stop_CPU_application.ToString()+"\n";             OUT+="GPU:"+"\n";             //альтернативные действия для реализации алгоритма korenXN.exe x64 использующего для вычислений GPU             DateTime running_GPU_application = DateTime.Now;             Process procGPU = Process.Start("korenXN.exe");             while (!procGPU.HasExited) ;             DateTime stop_GPU_application = DateTime.Now;             string[] outs2 = File.ReadAllLines("out.txt");             File.Delete("out.txt");             if (outs2.Length > 0)             {                 for (int j = 0; j < outs2.Length; j++)                 {                     OUT+=outs2[j]+"\n";                 }             }             else { OUT+="no values"+"\n"; }             OUT+="running_GPU_application:" + running_GPU_application.ToString()+"\n";             OUT+="stop_GPU_application:" + stop_GPU_application.ToString()+"\n";             return OUT;//возвратить результат         }         static void Main()         {             Int64 start = 36*36;//начальное значение входного числа             Int64 degree_of_strat = 500;//начальное значение максимальной степени             int size = 20-5;//количество элементов в массиве             Int64[] Number = new Int64[size];//массив входных чисел             Int64[] Degree_of = new Int64[size];//массив максимальных степеней             string[]outs= new string[size];//масссив результатов             for (int n = 0; n < size; n++)             {                 if (n % 2 == 0)                 {                     Number[n] = start * start;                 }                 else                 {                     Number[n] = start * degree_of_strat;                     Number[n] -= n + n;                 }                 start += 36*36;                 Degree_of[n] = degree_of_strat;                 degree_of_strat +=1000;             }             for (int n = 0; n < size; n++)             {                 outs[n] = Upload(Number[n], Degree_of[n]);                 Console.WriteLine(outs[n]);             }             System.IO.File.WriteAllLines("result.txt", outs);//записать результаты в файл result.txt         }     } }  

, который создавал файл с исходными данными, затем последовательно запускал exe файлы алгоритмов использующих CPU или GPU и замерял время их работы, затем заносил это время и результаты работы алгоритмов в файл result.txt. Для замера загруженности процессора использовался диспетчер задач windows.

Результаты теста превидены в таблице:

Как видно из таблицы, время выполнения алгоритма на GPU немного больше, чем на CPU.
Однако, отмечу, что вовремя работы алгоритма использующего для вычислений GPU загрузка им CPU, в Диспетчере задач, не превышала 30%, в то время как алгоритм использующий для вычислений CPU, загружал его на 68-85%, что в свою очередь иногда приводило к замедлению других приложений. Также, ниже приведен график, показывающий различие во
времени выполнения (по оси Y)CPU и GPU в зависимости от входного числа(по оси X).

график

Далее я решил провести тестирование при процессоре нагруженном другими приложениями. Процессор был нагружен так, что запущенный в приложение тест, не занимал больше 55% ресурсов процессора. Результаты теста приведены ниже:

График

Как видно из таблицы, в случае с нагруженным CPU, выполнение вычислений на GPU, дает прирост производительности, так как загруженность процессора в 30% укладывается в лимит 55%, а в случае использования CPU для вычислений, его загрузка составляет 68-85% , что тормозит работу алгоритма, если CPU нагружен другими приложениями.

Поэтому, можно сделать вывод, что использование GPU для вычислений, не обязательно должно давать более быструю работу алгоритма, однако, оно способно разгрузить CPU, что может играть роль, если он нагружен другими приложениями.

ссылка на оригинал статьи https://habr.com/ru/post/525892/