Professional Documents
Culture Documents
Подзірей
Подзірей
КУРСОВА РОБОТА
з дисципліни «Системне програмування»
на тему: «Розробка профайлера для процесорів ARC»
Оцінка
Дата захисту _
Члени комісії
(підпис)(прізвище та ініціали)
(підпис)(прізвище та ініціали)
_
(підпис)(прізвище та ініціали)
Київ 2023
1
Міністерство освіти і науки України
Відокремлений структурний підрозділ «Фаховий коледж інженерії та управління
Національного авіаційного університету»
ЗАТВЕРДЖУЮ
Голова комісії
(підпис) (ПІБ)
« _» 2023 р.
ІНДИВІДУАЛЬНЕ ЗАВДАННЯ
Студента(ки) Подзірея Б.В. спеціальності Комп’ютерна інженерія курсу 4
ТЕМА «Розробка профайлера для процесорів ARC»
Завдання отримала
(підпис)
2
Тема: «Розробка профайлера для процесорів ARC»
4. Розробка і програмування.
5. Тестування додатку.
7. Коригування роботи за
результатами попереднього захисту.
3
ЗМІСТ
ВСТУП..............................................................................................................................5
РОЗДІЛ 1. АНАЛІЗ ПОСТАВЛЕНОЇ ЗАДАЧІ ТА ФОРМУВАННЯ ВИМОГ.........6
1.1 Огляд технік профілювання..................................................................................6
1.2 Профілювання з використанням вбудованих засобів.........................................8
1.3 Вимоги до створення програмної реалізації......................................................10
РОЗДІЛ 2. ПРОГРАМНА РЕАЛІЗАЦІЯ СИСТЕМИ.................................................11
2.1 Створення UML діаграм додатку.......................................................................11
2.2 Розрахування метрик...........................................................................................14
2.3 Граф викликів.......................................................................................................15
2.4 Обробка результатів.............................................................................................17
РОЗДІЛ 3. ТЕСТУВАННЯ ТА КЕРІВНИЦТВО КОРИСТУВАЧА.........................19
3.1 Тестування програмної реалізації покращення якості.....................................19
3.2 Інструкція користувача........................................................................................20
ВИСНОВОК...................................................................................................................22
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ.....................................................................23
ДОДАТОК 1...................................................................................................................25
4
ВСТУП
5
РОЗДІЛ 1. АНАЛІЗ ПОСТАВЛЕНОЇ ЗАДАЧІ ТА ФОРМУВАННЯ ВИМОГ
6
варіант – надсилати результати вимірювань через зовнішній канал. В даному
випадку все сильно залежить від пропускної здатності цього каналу і вартості
передачі даних. Наприклад, використовуючи перший підхід до накопичення
буфера, окремий потік для відправки вмісту цього буфера та досить швидкий
канал, цей підхід можна використовувати для отримання відносно точних
результатів.
Другим поширеним підходом до профілювання є профілювання на основі
вибірки, статистичне профілювання. Одним із прикладів утиліти, яка реалізує цей
підхід, є Intel VTune. Опис реалізації наведено на сторінці. Він полягає в
регулярному зчитуванні значення поточного індикатора інструкції та перевірці,
чи не потрапляє воно в один із заздалегідь визначених діапазонів. Наприклад,
діапазони, що відповідають кожній функції, отримуються перед запуском
програми. Далі створюється гістограма кількості звернень до різних функцій, що
дозволяє приблизно оцінити найдорожчі функції.
Такий підхід також має ряд істотних недоліків. По-перше, читання позиції
поточної інструкції може вплинути на процес керування програмою, поки він
повністю не зупиниться. Особливо це видно під час профілювання коду, часу
виконання на віддаленому чіпі. У цьому випадку спроба прочитати регістр
призводить до дорогого ланцюга повідомлень через канал налагодження і впливає
на внутрішній стан процесора. По-друге, такий підхід не дає жодної інформації
про реалізацію землі в реальному часі. Навпаки, вони просто стверджують, що
кожен сайт, ймовірно, займе відповідну частку загального часу.
Крім того, деякі невеликі, але часто звані функції можна повністю
ігнорувати в цьому підході. Цей випадок повністю продемонстрований у RS
Одера в тесті «Пила».
Далі ми розглянемо інструменти для профілювання на ARC.
Synopsys надає набір інструментів розробки, які можна використовувати для
дослідження та оптимізації продуктивності ваших програм. Кожен з них має свої
переваги, недоліки та сфери використання.
7
xCAM є інструментом для створення точних програмних моделей
процесора логічного вентиля. Основною перевагою таких моделей є можливість з
абсолютною точністю аналізувати продуктивність по відношенню до циклів
процесора. Однак швидкість виконання моделі на кілька порядків нижча за
тактову частоту готового процесора, що створює додаткові незручності для
користувача під час профілювання. Крім того, взаємодія програми з іншими
компонентами системи вимагає створення їх моделі.
nSIM є програмним симулятором процесора на рівні команд. Він має значно
вищу швидкість роботи в порівнянні з xCAM, але не гарантує точного
моделювання щодо кількості циклів, витрачених на виконання інструкцій. Його
можна використовувати для пошуку дорогих областей у програмі, але він не
підходить для отримання точних результатів. Крім того, як і у випадку з xCAM,
взаємодія з пристроями сторонніх розробників вимагає створення компонентів,
які її імітують.
RTT (Tracing в реальному часі) — це здатність процесора генерувати велику
кількість інформації про процес.
грам в режимі реального часу за допомогою спеціального модуля,
включеного в схему. Цей інструмент не дозволяє безпосередньо отримувати
інформацію про цикли, які процесор витратив на виконання певного розділу, але
повідомляє про різні події, такі як читання з пам’яті чи запис у пам’ять, взаємодія
з регістрами, а також надає повне відстеження інструкцій. . Інструмент поєднує в
собі переваги відсутності втручання в хід програми та виконує аналіз на повній
швидкості процесора. Основним недоліком є необхідність використання
спеціального обладнання з швидким каналом зв'язку, що дозволяє отримувати
великий обсяг інформації. Таке обладнання досить дороге і може бути недоступне
користувачам.
8
Перший полягає у вимірюванні продуктивності шляхом додавання
додаткових модулів моніторингу до схеми процесора, які підключені до
необхідних компонентів, і завантаження отриманої схеми процесора разом з
іншими модулями в програмовану логічну інтегральну схему (профілювання на
основі FPGA). Наприклад, ви можете додати лічильники, які вмикаються, коли
інструкція виконується за однією адресою, і вимикаються, коли інструкція
виконується за іншою, вимірюючи час виконання цього розділу в цілому та
отримуючи щось подібне до профілювання за допомогою інструментів коду. , але
без додаткових втрат продуктивності та змін програми.
Основною перевагою такого підходу є відсутність будь-якого втручання в
процес виконання коду і, таким чином, забезпечення максимально точних
результатів вимірювань, а також можливість включення.
Це може бути як завгодно складним і функціональним розширенням
(звісно, до обмеження обсягу FPGA). Найбільш істотним недоліком є необхідність
розробки окремого вимірювального модуля для кожної моделі процесора, а в
деяких випадках і для кожної програми, що розглядається. Крім того, такий підхід
не дає можливості оцінити продуктивність на реальному процесорі.
Другий — використання заздалегідь розроблених і жорстко
запрограмованих лічильників різних подій, що відбуваються в процесорі
(комп'ютери продуктивності, лічильники потужності), починаючи з виконання
однієї інструкції і закінчуючи подіями високого рівня, такими як збій буфера
(Профілювання на основі апаратного лічильника). Такий підхід поєднує точність
вимірювання з можливістю коригування лічильників під час роботи для кожної
перевіреної програми та цікавих подій. Крім того, такі лічильники часто містяться
у вже використовуваному готовому процесорі, що дозволяє вивчати поведінку
програми в реальних умовах. Основним недоліком використання лічильників є,
по-перше, їх обмежена кількість і, по-друге, відносно погана конфігураційність
порівняно з перепрограмуванням FPGA або введенням коду вимірювання в
досліджувану програму.
9
1.3 Вимоги до створення програмної реалізації
Метою даної роботи є впровадження профайлера, що дозволяє виконувати
аналіз продуктивності при виконанні програм на процесорах ARC.
Головні ролі:
• вивчити існуючі методи розвитку викладачів та розглянути інструменти
вимірювання продуктивності, що надаються процесорами ARC;
• сформулювати необхідні для користувача сценарії профілювання та
розробити алгоритми їх реалізації;
• розробити та впровадити систему, яка забезпечує можливість виконання
заданих сценаріїв;
• перевірити отриманий розчин і оцінити точність вимірювань.
Для забезпечення нормальної роботи програми повинна бути використана
наступна конфігурація комп’ютера:
‒ мінімальний центральний процесор класу Intel Core i3-4100U 1,8 ГГц;
обсяг оперативної пам’яті не менше 1Гб;
‒ стандартний маніпулятор «миша»;
‒ стандартний SVGA монітор;
‒ операційна система типу Windows, 7, 8, 10.
10
РОЗДІЛ 2. ПРОГРАМНА РЕАЛІЗАЦІЯ СИСТЕМИ
11
Рис. 2.2 - Структура модуля вимірів
12
• Сформулювати загальні вимоги до функціональної поведінки
пропонованої системи.
• Розробити вихідну концептуальну модель системи для її подальшого
уточнення у вигляді логічної та фізичної моделей.
• Підготувати вихідну документацію для взаємодії розробників системи з її
замовниками та користувачами.
Суть цієї діаграми полягає в наступному: запропонована система
представляється у вигляді набору сутностей або акторів, які взаємодіють із
системою за допомогою так званих випадків використання. У цьому випадку
актор або актор — це будь-яка сутність, яка взаємодіє з системою ззовні. Це може
бути людина, технічний пристрій, програма або будь-яка інша система, яка може
слугувати джерелом впливу на змодельовану систему, як визначено розробником.
Варіант використання, у свою чергу, використовується для опису послуг, які
система надає суб’єкту. Іншими словами, кожен варіант використання визначає
набір дій, які система виконує в діалозі з актором.
На рисунку 2.3 продемонстровано UML Use Case діаграму програми, що
розробляється.
13
Діаграми послідовності іноді називають діаграмами подій відповідно
сценарії подій.
Діаграма послідовності системи управління представлена на рисунку 2.4.
14
Рис.2.5 - Приклад графіка для обчислення показників.
Далі всі доступні вихідні дані сортуються і всі залежні від них метрики
позначаються як такі, що мають ці дані. Якщо після наступної серії оцінок
метрика має всі необхідні дані, вона обчислюється і додається до результату.
Такий підхід дозволяє уникнути повного переліку можливих показників,
який у переважній більшості випадків не є необхідним, оскільки користувач
найчастіше збирає дані для однієї або двох метрик із сотень можливих.
15
Підрахунок подій у фрагменті коду.
Це вимірювання отримує від користувача необхідний набір вимірюваних
подій і вимагає відповідної кількості лічильників. Крім того, під час ініціалізації
може бути використаний один із двох методів активації лічильників на місці:
контрольно-вимірювальний або діапазон. Після завершення вимірювання
значення використаних лічильників додаються до результатів вимірювань з
позначкою про належність до відповідної області. Одночасно протягом усього
вимірювання
Profiler не заважає виконанню програми. Таким чином, це вимірювання
реалізує сценарій автоматичного вимірювання подій у розділі коду.
Цей тип вимірювань вимагає інформації з графіка виклику, яку можна
отримати за допомогою інших відповідних вимірювань раніше або завантажити
ззовні. Користувач також повинен вказати метрику, за якою буде обчислюватися
батьківський рейтинг дитини, мінімальне значення метрики, точку, в якій
виконується реконфігурація, і функцію, з якої починається аналіз. За
замовчуванням аналіз починається з усіх функцій, які не викликаються іншими,
оскільки вони потенційно можуть бути точками входу в програму.
Аналіз проводиться наступним чином.
Спочатку графік викликів масштабується, а функції додаються до черги в
тому ж порядку. Цей порядок важливий, оскільки він мінімізує помилку при
вимірюванні функцій верхнього рівня, яка виникає внаслідок додаткових витрат
на функції нижнього рівня. Крім того, це дозволяє розрахувати оцінку з часом і
відкинути явно нерелевантні функції. Це означає, що на той час, коли функція
витягується з черги, функції, які її викликають, ймовірно, вже були
проаналізовані. Слід зазначити, що можна гарантувати обчислення оцінки для
всіх функцій, які мають предків, але це недоцільно, тому що в цьому випадку,
навіть якщо лічильники є, доведеться дочекатися завершення аналізу предків.
перш ніж продовжити аналіз самої функції, а деякі лічильники залишаються
неактивними. Запропонований підхід дозволяє, хоча і не ідеально, розділити
16
лічильники, що залишилися, між функціями, для яких ще неможливо оцінити
розрахунком.
По-друге, вводиться поняття аналітичного кроку. На кожному кроці циклу
одна вершина витягується з черги на стільки, скільки необхідно
Даний розрахунок метрики - це кількість лічильників. Потім метричний бал
для витягнутої функції обчислюється її батьками, і якщо оцінка менша за вказане
число, функція ігнорується. Якщо функцію не було вимкнено, створюється вимір
"кількість подій в області" і зберігається його ідентифікатор. Коли доступні
лічильники закінчаться, виконання програми починається до моменту, коли
виконується реконфігурація. За бажанням, програму можна перезапустити перед
кожним кроком.
При досягненні точки реконфігурації виконуються наступні дії. Усі створені
вимірювання "кількості подій на сайті" завершено. На основі їх результатів
розраховуються значення метрики для кожної аналізованої функції. Виконується
наступний етап аналізу.
Аналіз завершується або на запит користувача, або відразу після
спустошення черги. При необхідності черга повторно ініціалізується.
17
По-третє, результати можна представити у вигляді анотованого графіка
викликів DOT. У цьому випадку обчислюються метрики і їх результат
записується разом із вихідними даними як додатковий текст до вузла на графіку.
Крім того, графік можна візуалізувати за допомогою graphviz або будь-якої
подібної програми.
18
РОЗДІЛ 3. ТЕСТУВАННЯ ТА КЕРІВНИЦТВО КОРИСТУВАЧА
19
Після виконання тестування можна стверджувати, що програма виконується
коректно.
20
nettle_aes 138350 10 12-659 12 54.9 0.02-1.76
nettle_sha256 14077 7 13-499 9 55.4 0.34-12.05
slre 92523 13 77-45949 1168 39.3 13.44-65.09
st 701853 9 9-29018 613 47.3 0.05-6.48
statemate 4403 4 110-239 5 47.8 2.86-5.43
ud 17212 2 19-70 2 35.0 0.15-0.41
zlib 234445 28 1-298 28 10.6 0.0-4.83
21
ВИСНОВОК
22
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ
23
13. Sarker, R.A. Heuristic and optimization for knowledge discovery / Sarker
R.A., Abbass H.A., Newton C.S.. – М.: [не вказано], 2002. – 129 с.
14. Scheutz, M. Computationalism. New directions / Scheutz M.. – М.: [не
вказано], 2002. – 954 c.
15. Weiss, G. Multiagent Systems: A Modern Approach to Distributed Modern
Approach to Artificial Intelligence / Weiss G. – М.: [не зазначено], 1999. – 946 c.
16. Wendy, A. Kellogg New Agenda for Human-Computer Interaction
(Human- Computer Interaction, Vol 15, Nos. 2 & 3) / Wendy A. Kellogg, Clayton
Lewis, Peter Polson. – Москва: Вогні, 2006. – 833 c.
17. Ендрю Троелсен Мова програмування C# 2010 та платформа.net 4.0 5е
видання. 2011. – 1392с.
18. Розміщено Піменов В.Ю. Обчислювально-ефективний метод пошуку
нечітких дублікатів у колекції зображень. 2009-19с.
19. Herbert Bay, Andreas Ess, Tinne Tuytelaars, Luc Van Gool Speeded-Up
Robust Features (SURF) 2008 - 14с
20. Лабор В.В. Сі Шарп: Створення програм для Windows - Мі.: Харвест,
2003. - 384с.
21. Фролов А.В., Фролов Г.В. Мова С# Самовчитель, 2003. - 557с.
24
ДОДАТОК 1
@RestController
@RequestMapping("/api/mirf")
public class MirfController {
@Autowired
PipelineExecutor pipelineExecutor;
@Autowired
FileService fileService;
@Autowired
PipelineJobRepository pipelineJobRepository;
@GetMapping("triggerPipeline")
public void triggerPipeline() throws Exception {
pipelineExecutor.triggerPipeline();
}
@PostMapping("mirfSuccess")
public void getResultFromPipeline(@RequestParam("sessionId") String
sessionId,
@RequestParam("file") MultipartFile resultZipFile)
throws IOException, ClassNotFoundException {
InputStream zipInputStream = resultZipFile.getInputStream();
byte[] zipInBytes = zipInputStream.readAllBytes();
25
log.info("Received result from MIRF for session: {}, resultSize: {}",
sessionId, resultZipFile.getSize());
pipelineJobRepository.findAll().forEach(it ->
System.out.println(it.getMirfSessionid()));
PipelineJob relatedPipelineJob =
pipelineJobRepository.findByMirfSessionid(sessionId).get(0);
try {
byte[] resultFileInBytes = MirfZipUtils.unzipResultArchive(zipInBytes);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("-dd-MM-
yyyy-HH-mm-ss");
String startedTime =
formatter.format(relatedPipelineJob.getStartedTime());
FileObject outputFile = fileService.saveFile("pipeline-result" +
startedTime + ".pdf", resultFileInBytes, relatedPipelineJob.getCreator().getId());
relatedPipelineJob.setOutputFile(outputFile);
relatedPipelineJob.setEndTime(LocalDateTime.now());
relatedPipelineJob.setExecutionStatus(PipelineJobStatus.COMPLETED_OK);
} catch (Exception ex) {
relatedPipelineJob.setExecutionStatus(PipelineJobStatus.COMPLETED_ERROR);
log.info("Unable to save result from MIRF, sessionId: {}, reason:{}",
sessionId, ex.getMessage());
}
pipelineJobRepository.save(relatedPipelineJob);
}
@PostMapping("mirfError")
26
public void getErrorFromPipeline(@RequestParam("sessionId") String
sessionId,
@RequestParam("reason") String failReason) {
log.info("Received error from MIRF for session: {}, reason: {}", sessionId,
failReason);
PipelineJob relatedPipelineJob =
pipelineJobRepository.findByMirfSessionid(sessionId).get(0);
relatedPipelineJob.setExecutionStatus(PipelineJobStatus.COMPLETED_ERROR);
pipelineJobRepository.save(relatedPipelineJob);
}
}
@Service
public class MirfOrchestratorClient {
@Value("${mirf.orchestrator.url}")
private String mirfOrchestratorUrl;
@Value("${mirf.orchestrator.port}")
private String mirfOrchestratorPort;
@Value("${mirf.orchestrator.url.pipeline.start}")
private String mirfPipelineEndPoint;
@Value("${mirf.orchestrator.url.sessionId}")
private String mirfSessionIdEndpoint;
@Value("${mirf.orchestrator.url.registerClient}")
27
private String mirfRegisterClientEndpoint;
28
URI repositoryUri = new URI("http", null, mirfOrchestratorUrl,
Integer.parseInt(mirfOrchestratorPort), null, null, null);
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addTextBody("sessionId", sessionId,
ContentType.DEFAULT_BINARY);
builder.addTextBody("pipeline", pipelineConfiguration,
ContentType.DEFAULT_BINARY);
29
CloseableHttpResponse response = httpClient.execute(request)) {
@Value("${mirf.repository.url}")
private String mirfRepositoryUrl;
@Value("${mirf.repository.port}")
private String mirfRepositoryPort;
@Value("${mirf.repository.url.archive}")
private String mirfRepositoryArchiveEndPoint;
/**
* @param filename name of archive, it should be in *.zip format
*/
public Boolean sendArchive(String sessionId, String filename, byte[]
30
zipArchive) throws IOException, URISyntaxException, InterruptedException {
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addTextBody("sessionId", sessionId,
ContentType.DEFAULT_BINARY);
builder.addBinaryBody("file", zipArchive,
ContentType.DEFAULT_BINARY, filename);
} @Service
@Lazy
public class OrthancInstancesClient {
@Value("${orthanc.url.instances}")
private String orthancInstancesUrl;
31
@Value("${orthanc.credentials.username}")
private String orthancUsername;
@Value("${orthanc.credentials.password}")
private String orthancPassword;
@PostConstruct
public void init() throws IOException {
credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials(orthancUsername,
orthancPassword)
);
}
32
String jsonResponse = EntityUtils.toString(entity);
}
}
}
request.setEntity(requestEntity);
request.setHeader("Accept", "application/dicom");
request.setHeader("Content-type", "application/dicom");
33
"/file");
request.setHeader("Accept", "application/dicom");
request.setHeader("Accept", "image/jpeg");
34
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream is = entity.getContent();
byte[] bytes = IOUtils.toByteArray(is);
return new ByteArrayInputStream(bytes);
}
}
return null;
}
35
Map<String, Object> resultMap = objectMapper.readValue(json, new
TypeReference<Map<String,Object>>(){});
return resultMap.get("ID").toString();
}
}
36