From 2d81ec7cc10a5dc80b930dd662a3e8aaaf7ef72a Mon Sep 17 00:00:00 2001 From: pravdan Date: Fri, 8 May 2026 22:33:47 +0300 Subject: [PATCH 01/11] Add Daniil_Pravkin_report.tex Add sgemm_graph.png --- Daniil_Pravkin/Daniil_Pravkin_report.tex | 151 +++++++++++++++++++++++ Daniil_Pravkin/sgemm_graph.png | Bin 0 -> 27683 bytes main.tex | 3 +- 3 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 Daniil_Pravkin/Daniil_Pravkin_report.tex create mode 100644 Daniil_Pravkin/sgemm_graph.png diff --git a/Daniil_Pravkin/Daniil_Pravkin_report.tex b/Daniil_Pravkin/Daniil_Pravkin_report.tex new file mode 100644 index 0000000..cb472df --- /dev/null +++ b/Daniil_Pravkin/Daniil_Pravkin_report.tex @@ -0,0 +1,151 @@ +% Данный файл распространяетсяя под лицензией CC BY 4.0. Текст лицензии размещён на https://creativecommons.org/licenses/by/4.0/ +% (c) Кафедра системного программирования, 2025 + +\documentclass[a4paper]{article} + +\usepackage[a4paper, top=8mm, bottom=8mm, left=8mm, right=8mm]{geometry} + +\usepackage{polyglossia} +\setdefaultlanguage[babelshorthands=true]{russian} +\setotherlanguage{english} + +\usepackage{fontspec} +\setmainfont{FreeSerif} +\newfontfamily{\russianfonttt}[Scale=0.7]{DejaVuSansMono} + +\usepackage[tiny, compact]{titlesec} + +\usepackage{titling} +\setlength{\droptitle}{-1cm} +\pretitle{\begin{center}\begin{bfseries}\Large} +\posttitle{\par\end{bfseries}\end{center}} +\preauthor{\begin{center}\normalsize} +\postauthor{\par\end{center}\vspace{-1.8cm}} + +\usepackage{hyperref} +\usepackage{bookmark} +\usepackage{csquotes} +\usepackage{graphicx} +\usepackage[table]{xcolor} +\usepackage{url} +\usepackage{float} +% Сюда можно дописывать нужные вам пакеты. + +\title{Vortex: освоение FPGA-стека} + +\author{Правкин Даниил Денисович} + +% Дата много места занимает, её лучше не указывать. +\date{} + +\begin{document} + +\maketitle + +\begin{flushright} + Группа: \enquote{25.Б73-мм} + + Кафедра: \emph{кафедра, на которой планируется защита/сдача работы} + + % Степень/звание и должность научника мы лучше вас знаем, их можно не указывать. + Научный руководитель: \emph{ФИО научного руководителя} + + % А вот про консультанта укажите официальное место работы, с "ООО" или чем-то таким, и должностью желательно по трудовой, не просто "techlead". Выясните у консультанта. + % Консультант: \emph{место работы, должность, степень, звание (если есть) консультанта} + + Номер семестра практики: 2 +\end{flushright} + + +\section{Постановка задачи} + +% Буквально парой предложений ввести в контекст, обязательно сформулировать цель работы. Если работа делается где-то глубоко внутри проекта, на введение можно потратить больше места, чтобы подвести читателя от сути проекта в целом к тому, что конкретно вам надо было сделать. Только без воды, никакого "в современном мире"! +Vortex - это проект с открытым исходным кодом для поддержки GPGPU на основе расширений RISC-V ISA, с возможностью аппаратной конфигурации. Целью работы является получение навыков работы с FPGA-стеком. + +% Это пояснение актуальности. Тут обязательно надо обрисовать полезность вашей работы для конечного пользователя (и заодно как-то описать, кто такой ваш конечный пользователь --- может, это соседняя команда). Даже если вы делаете работу "глубоко внутри", выясните у консультанта, чем это людям поможет. И опишите, кто выступал в роли "заказчика" вашей работы, т.е. кто и зачем предложил задачу. Можно без конкретных имён, но названия организаций вполне желательны. +Результаты работы необходимы для дальнейшей работы с Vortex: сборка Vortex, оценка потребления ресурсов конфигурации, сравнение различных конфигураций. + +\section{Описание предлагаемого решения} + +% Раздел пишется в свободной форме, с минимумом технических подробностей (можно приводить ссылки на более подробные документы). +Для получения навыков работы с Vortex, был проведён эксперимент по измерению масштабируемости функции умножения матриц. +% Вот это важно, опишите кратко, что использовали +Реализация решения осуществлялась с использованием Docker-контейнера и симулятора SimX, поскольку он обеспечивает достаточно высокую потактовую точность, затрачивая при этом меньше времени на выполнение, чем RTL-симулятор. + +\section{Эксперименты} + +\subsection*{Введение} +Vortex использует модель исполнения SIMT (Single Instructions Multiple Threads)\footnote{Информация из документации Vortex о микроархитектуре на сайте github.com (\url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md}) (27.04.2026)}, в которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads) (наименьшие единицы вычисления, которые выполняются параллельно) и варпов (warps) (набор потоков, выполняющих одну и ту же инструкцию). Таким образом достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц (\url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html})}. + +\subsection*{Цель} +Проанализировать масштабируемость функции умножения матриц при увеличение количества ядер и фиксированном объёме входных данных. + +\subsection*{Входные данные} +Для эксперимента была выбрана матрица размера 512x512 с целью получения более реалистичной производительности. Для алгоритма требуется память для двух перемножаемых матриц и одной итоговой, следовательно, объём 3-ёх матриц данного размера --- 3~МиБ, что превышает объём общей памяти (Local Memory) (128 КиБ), L1-кэша (16~КиБ), L2-кэша (1~МиБ) и L3-кэша (2~МиБ)\footnote{Объёмы общей памяти и l1/l2/l3-кэшей взяты со страниц Vortex на сайте github.com (объём общей памяти: \url{https://github.com/vortexgpgpu/vortex/blob/master/hw/rtl/mem/VX_local_mem.sv} оъёмы кэшей: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/simulation.md}) (26.04.2026)}, следовательно, программа будет больше взаимодействовать с основной памятью. + +\subsection*{Проведение эксперимента} + +Порядок выполнения тестов: +\begin{enumerate} + \item Отключение графической оболочки, для повышения скорости симуляции. + \item Запуск Docker-контейнера. + \item Запуск тестов и запись результатов. +\end{enumerate} + +Сперва надо было подобрать оптимальную конфигурацию, для более реалистичной производительности. Подбор производился при cores=8, потому что большее количество ядер порождает большую нагрузку на память, то есть более реалистичную производительность. + +Далее были выполнены тесты с оптимальной конфигурацией, но изменяемым количеством ядер. Значения количества ядер кратны степеням 2, чтобы обеспечить более равномерное распределение нагрузки между ядрами, так как размер матрицы тоже кратен степени 2. + +\subsection*{Результаты и анализ} +В результате поиска аппаратной конфигурации (табл. \ref{tab:optimal_for_8}), наиболее оптимальной при восьми ядрах оказалась следующая: clusters=1, warps=8, threads=64, l2cache, l3cache. + +По результатам тестов по измерению масштабируемости (рис. \ref{figure:sgemm_graph}), при увеличении количества ядер от 1 до 16, количество тактов уменьшается, а при cores=16 достигает наименьшего значения. При дальнейшем увеличении количества ядер (начиная с 32), количество тактов начинает возрастать. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу ядер, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество тактов больше, чем при 16-ти ядрах. Таким образом, для умножения матриц 512x512 при clusters=1, warps=8, threads=64, l2cache, l3cache наименьшее количество тактов достигается при использовании 16-ти ядер. + + +\begin{table} +\centering +\begin{tabular}{| c|c|c |} + \hline + Кол-во групп потоков & Кол-во потоков & Кол-во тактов (млн.) \\ + \hline + 2 & 16 & 43,0 \\ + 2 & 32 & 22,8 \\ + 2 & 64 & 13,8 \\ + + 4 & 16 & 30,3 \\ + 4 & 32 & 16,4 \\ + 4 & 64 & 13,7 \\ + + 8 & 16 & 30,6 \\ + 8 & 32 & 18,8 \\ + \rowcolor{lightgray} + 8 & 64 & 13,6 \\ + + 16 & 16 & 33,4 \\ + 16 & 32 & 18,8 \\ + 16 & 64 & 14,2 \\ + \hline +\end{tabular} +\caption{\label{tab:optimal_for_8} Число тактов, затраченных на выполнение алгоритма умножения матриц размера 512x512 при cores=8 clusters=1, l2cache, l3cache и при различных значениях числа потоков и групп потоков. Выделенная строка --- конфигурация, при которой затрачено наименьшее число тактов.} +\end{table} + +\begin{figure} + \centering + \includegraphics[width=0.8\linewidth]{sgemm_graph.png} + \caption{\label{figure:sgemm_graph} Изменение числа тактов, затраченных на выполнение алгоритма умножения матриц, при clusters=1, warps=8, threads=64, l2cache, l3cache и различных значениях количества ядер} +\end{figure} + +\section{Заключение} + +В ходе выполнения работы получены следующие результаты: + +% ниже списком перечисляете то, что выносится как результат практики. + +\begin{itemize} + \item произведено сравнение затрачиваемого количества тактов различными конфигурациями при выполнении функции умножения матриц Vortex + \item проанализирована масштабируемость функции умножения матриц +\end{itemize} + +Техническая документация: \url{https://github.com/vortexgpgpu/vortex} . + +\end{document} \ No newline at end of file diff --git a/Daniil_Pravkin/sgemm_graph.png b/Daniil_Pravkin/sgemm_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..679dbcc966bbb7edc57fbfdf3b477ab660cb4ba8 GIT binary patch literal 27683 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 Date: Fri, 29 May 2026 20:08:05 +0300 Subject: [PATCH 02/11] Correction of report. --- Daniil_Pravkin/Daniil_Pravkin_report.tex | 38 ++++++++---------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/Daniil_Pravkin/Daniil_Pravkin_report.tex b/Daniil_Pravkin/Daniil_Pravkin_report.tex index cb472df..8b3ac30 100644 --- a/Daniil_Pravkin/Daniil_Pravkin_report.tex +++ b/Daniil_Pravkin/Daniil_Pravkin_report.tex @@ -29,13 +29,11 @@ \usepackage[table]{xcolor} \usepackage{url} \usepackage{float} -% Сюда можно дописывать нужные вам пакеты. \title{Vortex: освоение FPGA-стека} \author{Правкин Даниил Денисович} -% Дата много места занимает, её лучше не указывать. \date{} \begin{document} @@ -45,13 +43,11 @@ \begin{flushright} Группа: \enquote{25.Б73-мм} - Кафедра: \emph{кафедра, на которой планируется защита/сдача работы} + Кафедра: Кафедра системного программирования - % Степень/звание и должность научника мы лучше вас знаем, их можно не указывать. - Научный руководитель: \emph{ФИО научного руководителя} - % А вот про консультанта укажите официальное место работы, с "ООО" или чем-то таким, и должностью желательно по трудовой, не просто "techlead". Выясните у консультанта. - % Консультант: \emph{место работы, должность, степень, звание (если есть) консультанта} + Научный руководитель: Григорьев Семён Вячеславович + Номер семестра практики: 2 \end{flushright} @@ -59,23 +55,17 @@ \section{Постановка задачи} -% Буквально парой предложений ввести в контекст, обязательно сформулировать цель работы. Если работа делается где-то глубоко внутри проекта, на введение можно потратить больше места, чтобы подвести читателя от сути проекта в целом к тому, что конкретно вам надо было сделать. Только без воды, никакого "в современном мире"! -Vortex - это проект с открытым исходным кодом для поддержки GPGPU на основе расширений RISC-V ISA, с возможностью аппаратной конфигурации. Целью работы является получение навыков работы с FPGA-стеком. +Vortex --- это проект с открытым исходным кодом, предназначенный для поддержки вычислений на графических процессорах (GPGPU). Он реализован на основе расширений системы команд RISC-V ISA и предусматривает возможность аппаратной конфигурации. Целью данной работы является получение навыков работы с FPGA-стеком. -% Это пояснение актуальности. Тут обязательно надо обрисовать полезность вашей работы для конечного пользователя (и заодно как-то описать, кто такой ваш конечный пользователь --- может, это соседняя команда). Даже если вы делаете работу "глубоко внутри", выясните у консультанта, чем это людям поможет. И опишите, кто выступал в роли "заказчика" вашей работы, т.е. кто и зачем предложил задачу. Можно без конкретных имён, но названия организаций вполне желательны. Результаты работы необходимы для дальнейшей работы с Vortex: сборка Vortex, оценка потребления ресурсов конфигурации, сравнение различных конфигураций. \section{Описание предлагаемого решения} -% Раздел пишется в свободной форме, с минимумом технических подробностей (можно приводить ссылки на более подробные документы). -Для получения навыков работы с Vortex, был проведён эксперимент по измерению масштабируемости функции умножения матриц. -% Вот это важно, опишите кратко, что использовали -Реализация решения осуществлялась с использованием Docker-контейнера и симулятора SimX, поскольку он обеспечивает достаточно высокую потактовую точность, затрачивая при этом меньше времени на выполнение, чем RTL-симулятор. +Vortex использует модель исполнения SIMT (Single Instructions Multiple Threads)\footnote{Информация из документации Vortex о микроархитектуре на сайте github.com (\url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md}) (27.04.2026)}, в рамках которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads) - наименьших единиц вычисления, выполняемых параллельно, - и варпов (warps) которые представляют собой набор потоков, исполняющих одну и ту же инструкцию. За счёт этого достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц (\url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html}) (29.05.2026)}. -\section{Эксперименты} +С целью получения навыков работы с Vortex был проведён эксперимент по измерению масштабируемости функции умножения матриц. Реализация решения осуществлялась в среде Docker-контейнера с применением симулятора SimX, поскольку он обеспечивает достаточно высокую потактовую точность, затрачивая при этом меньше времени на выполнение, чем RTL-симулятор. -\subsection*{Введение} -Vortex использует модель исполнения SIMT (Single Instructions Multiple Threads)\footnote{Информация из документации Vortex о микроархитектуре на сайте github.com (\url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md}) (27.04.2026)}, в которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads) (наименьшие единицы вычисления, которые выполняются параллельно) и варпов (warps) (набор потоков, выполняющих одну и ту же инструкцию). Таким образом достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц (\url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html})}. +\section{Эксперименты} \subsection*{Цель} Проанализировать масштабируемость функции умножения матриц при увеличение количества ядер и фиксированном объёме входных данных. @@ -99,7 +89,7 @@ \subsection*{Проведение эксперимента} \subsection*{Результаты и анализ} В результате поиска аппаратной конфигурации (табл. \ref{tab:optimal_for_8}), наиболее оптимальной при восьми ядрах оказалась следующая: clusters=1, warps=8, threads=64, l2cache, l3cache. -По результатам тестов по измерению масштабируемости (рис. \ref{figure:sgemm_graph}), при увеличении количества ядер от 1 до 16, количество тактов уменьшается, а при cores=16 достигает наименьшего значения. При дальнейшем увеличении количества ядер (начиная с 32), количество тактов начинает возрастать. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу ядер, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество тактов больше, чем при 16-ти ядрах. Таким образом, для умножения матриц 512x512 при clusters=1, warps=8, threads=64, l2cache, l3cache наименьшее количество тактов достигается при использовании 16-ти ядер. +По результатам тестов по измерению масштабируемости (рис. \ref{figure:sgemm_graph}), при увеличении числа ядер от 1 до 16, количество тактов уменьшается, а при cores=16 достигает наименьшего значения. В диапазоне от 17 до 31 ядра в ходе экспериментов возникали ошибки, свидетельствовавшие о неудачной попытке разделить задачу между всеми ядрами. Например, при запуске конфигурации с 18~ядрами, в итоговой статистике для двух из них были выведены отрицательные значения количества выполненных инструкций и затраченных тактов. При дальнейшем увеличении числа ядер (начиная с 32), наблюдался рост количества тактов. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу ядер, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество превышает значение, полученное при 16-ти ядрах. Таким образом, для умножения матриц 512x512 при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) наименьшее количество тактов достигается при использовании 16-ти ядер. \begin{table} @@ -126,26 +116,24 @@ \subsection*{Результаты и анализ} 16 & 64 & 14,2 \\ \hline \end{tabular} -\caption{\label{tab:optimal_for_8} Число тактов, затраченных на выполнение алгоритма умножения матриц размера 512x512 при cores=8 clusters=1, l2cache, l3cache и при различных значениях числа потоков и групп потоков. Выделенная строка --- конфигурация, при которой затрачено наименьшее число тактов.} +\caption{\label{tab:optimal_for_8} Число тактов, затраченных на выполнение алгоритма умножения матриц размера 512x512 при фиксированных параметрах (cores=8 clusters=1, l2cache, l3cache) и при различных значениях числа потоков и групп потоков. Выделенная строка --- конфигурация, при которой затрачено наименьшее число тактов.} \end{table} \begin{figure} \centering \includegraphics[width=0.8\linewidth]{sgemm_graph.png} - \caption{\label{figure:sgemm_graph} Изменение числа тактов, затраченных на выполнение алгоритма умножения матриц, при clusters=1, warps=8, threads=64, l2cache, l3cache и различных значениях количества ядер} + \caption{\label{figure:sgemm_graph} Изменение числа тактов, затраченных на выполнение алгоритма умножения матриц, при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) и различных значениях количества ядер} \end{figure} \section{Заключение} В ходе выполнения работы получены следующие результаты: -% ниже списком перечисляете то, что выносится как результат практики. - \begin{itemize} - \item произведено сравнение затрачиваемого количества тактов различными конфигурациями при выполнении функции умножения матриц Vortex - \item проанализирована масштабируемость функции умножения матриц + \item Произведено сравнение количества тактов, затрачиваемых различными конфигурациями Vortex при выполнении функции умножения матриц. + \item Проанализирована масштабируемость функции умножения матриц. \end{itemize} -Техническая документация: \url{https://github.com/vortexgpgpu/vortex} . +Техническая документация: \url{https://github.com/Prosto-Dan/vortex_practice_1_year} . \end{document} \ No newline at end of file From aae4e1a777a94a7a1073637730a0802e6c4e32e9 Mon Sep 17 00:00:00 2001 From: Prosto-Dan Date: Sun, 7 Jun 2026 00:51:53 +0300 Subject: [PATCH 03/11] Fix report --- Daniil_Pravkin/Daniil_Pravkin_report.tex | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Daniil_Pravkin/Daniil_Pravkin_report.tex b/Daniil_Pravkin/Daniil_Pravkin_report.tex index 8b3ac30..c94f6d3 100644 --- a/Daniil_Pravkin/Daniil_Pravkin_report.tex +++ b/Daniil_Pravkin/Daniil_Pravkin_report.tex @@ -61,17 +61,17 @@ \section{Постановка задачи} \section{Описание предлагаемого решения} -Vortex использует модель исполнения SIMT (Single Instructions Multiple Threads)\footnote{Информация из документации Vortex о микроархитектуре на сайте github.com (\url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md}) (27.04.2026)}, в рамках которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads) - наименьших единиц вычисления, выполняемых параллельно, - и варпов (warps) которые представляют собой набор потоков, исполняющих одну и ту же инструкцию. За счёт этого достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц (\url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html}) (29.05.2026)}. +Vortex использует модель исполнения SIMT (Single Instruction Multiple Threads)\footnote{Информация из документации Vortex о микроархитектуре на сайте github.com (\url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md}) (27.04.2026)}, в рамках которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads) --- наименьших единиц вычисления, выполняемых параллельно, --- и варпов (warps), которые представляют собой набор потоков, исполняющих одну и ту же инструкцию. За счёт этого достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц (\url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html}) (29.05.2026)}. С целью получения навыков работы с Vortex был проведён эксперимент по измерению масштабируемости функции умножения матриц. Реализация решения осуществлялась в среде Docker-контейнера с применением симулятора SimX, поскольку он обеспечивает достаточно высокую потактовую точность, затрачивая при этом меньше времени на выполнение, чем RTL-симулятор. \section{Эксперименты} \subsection*{Цель} -Проанализировать масштабируемость функции умножения матриц при увеличение количества ядер и фиксированном объёме входных данных. +Проанализировать масштабируемость функции умножения матриц при увеличении количества ядер и фиксированном объёме входных данных. \subsection*{Входные данные} -Для эксперимента была выбрана матрица размера 512x512 с целью получения более реалистичной производительности. Для алгоритма требуется память для двух перемножаемых матриц и одной итоговой, следовательно, объём 3-ёх матриц данного размера --- 3~МиБ, что превышает объём общей памяти (Local Memory) (128 КиБ), L1-кэша (16~КиБ), L2-кэша (1~МиБ) и L3-кэша (2~МиБ)\footnote{Объёмы общей памяти и l1/l2/l3-кэшей взяты со страниц Vortex на сайте github.com (объём общей памяти: \url{https://github.com/vortexgpgpu/vortex/blob/master/hw/rtl/mem/VX_local_mem.sv} оъёмы кэшей: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/simulation.md}) (26.04.2026)}, следовательно, программа будет больше взаимодействовать с основной памятью. +Для эксперимента была выбрана матрица размера 512x512 с целью получения более реалистичной производительности. Для алгоритма требуется память для двух перемножаемых матриц и одной итоговой, следовательно, объём трёх матриц данного размера --- 3~МиБ, что превышает объём общей памяти (Local Memory) (128 КиБ), L1-кэша (16~КиБ), L2-кэша (1~МиБ) и L3-кэша (2~МиБ)\footnote{Объёмы общей памяти и l1/l2/l3-кэшей взяты со страниц Vortex на сайте github.com (объём общей памяти: \url{https://github.com/vortexgpgpu/vortex/blob/master/hw/rtl/mem/VX_local_mem.sv} оъёмы кэшей: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/simulation.md}) (26.04.2026)}; следовательно, программа будет больше взаимодействовать с основной памятью. \subsection*{Проведение эксперимента} @@ -82,14 +82,14 @@ \subsection*{Проведение эксперимента} \item Запуск тестов и запись результатов. \end{enumerate} -Сперва надо было подобрать оптимальную конфигурацию, для более реалистичной производительности. Подбор производился при cores=8, потому что большее количество ядер порождает большую нагрузку на память, то есть более реалистичную производительность. +Сперва надо было подобрать оптимальную конфигурацию для более реалистичной производительности. Подбор производился при cores=8, потому что большее количество ядер порождает большую нагрузку на память, то есть более реалистичную производительность. -Далее были выполнены тесты с оптимальной конфигурацией, но изменяемым количеством ядер. Значения количества ядер кратны степеням 2, чтобы обеспечить более равномерное распределение нагрузки между ядрами, так как размер матрицы тоже кратен степени 2. +Далее были выполнены тесты с оптимальной конфигурацией, но изменяемым количеством ядер. Значения количества ядер кратны степеням двойки, чтобы обеспечить более равномерное распределение нагрузки между ядрами, так как размер матрицы тоже кратен степени двойки. \subsection*{Результаты и анализ} -В результате поиска аппаратной конфигурации (табл. \ref{tab:optimal_for_8}), наиболее оптимальной при восьми ядрах оказалась следующая: clusters=1, warps=8, threads=64, l2cache, l3cache. +В результате поиска аппаратной конфигурации (табл. \ref{tab:optimal_for_8}) наиболее оптимальной при восьми ядрах оказалась следующая: clusters=1, warps=8, threads=64, l2cache, l3cache. -По результатам тестов по измерению масштабируемости (рис. \ref{figure:sgemm_graph}), при увеличении числа ядер от 1 до 16, количество тактов уменьшается, а при cores=16 достигает наименьшего значения. В диапазоне от 17 до 31 ядра в ходе экспериментов возникали ошибки, свидетельствовавшие о неудачной попытке разделить задачу между всеми ядрами. Например, при запуске конфигурации с 18~ядрами, в итоговой статистике для двух из них были выведены отрицательные значения количества выполненных инструкций и затраченных тактов. При дальнейшем увеличении числа ядер (начиная с 32), наблюдался рост количества тактов. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу ядер, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество превышает значение, полученное при 16-ти ядрах. Таким образом, для умножения матриц 512x512 при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) наименьшее количество тактов достигается при использовании 16-ти ядер. +По результатам тестов по измерению масштабируемости (рис. \ref{figure:sgemm_graph}), при увеличении числа ядер от 1 до 16 количество тактов уменьшается, а при cores=16 достигает наименьшего значения. В диапазоне от 17 до 31 в ходе экспериментов возникали ошибки, свидетельствовавшие о неудачной попытке разделить задачу между всеми вычислительными блоками. Например, при запуске конфигурации с 18~ядрами в итоговой статистике для двух из них были выведены отрицательные значения количества выполненных инструкций и затраченных тактов. При дальнейшем увеличении числа ядер (начиная с 32) наблюдался рост количества тактов. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу вычислительных блоков, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество превышает значение, полученное при 16 ядрах. Таким образом, для умножения матриц 512x512 при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) наименьшее количество тактов достигается при использовании 16 ядер. \begin{table} @@ -116,13 +116,13 @@ \subsection*{Результаты и анализ} 16 & 64 & 14,2 \\ \hline \end{tabular} -\caption{\label{tab:optimal_for_8} Число тактов, затраченных на выполнение алгоритма умножения матриц размера 512x512 при фиксированных параметрах (cores=8 clusters=1, l2cache, l3cache) и при различных значениях числа потоков и групп потоков. Выделенная строка --- конфигурация, при которой затрачено наименьшее число тактов.} +\caption{\label{tab:optimal_for_8} Число тактов, затраченных на выполнение алгоритма умножения матриц размера 512x512 при фиксированных параметрах (cores=8, clusters=1, l2cache, l3cache) и различных значениях числа потоков и групп потоков. Выделенная строка --- конфигурация, при которой затрачено наименьшее число тактов.} \end{table} \begin{figure} \centering \includegraphics[width=0.8\linewidth]{sgemm_graph.png} - \caption{\label{figure:sgemm_graph} Изменение числа тактов, затраченных на выполнение алгоритма умножения матриц, при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) и различных значениях количества ядер} + \caption{\label{figure:sgemm_graph} Изменение числа тактов, затраченных на выполнение алгоритма умножения матриц при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) и различных значениях количества ядер.} \end{figure} \section{Заключение} @@ -136,4 +136,4 @@ \section{Заключение} Техническая документация: \url{https://github.com/Prosto-Dan/vortex_practice_1_year} . -\end{document} \ No newline at end of file +\end{document} From 40f87921772b7de7e7c8b42559dc0d07777210cb Mon Sep 17 00:00:00 2001 From: Prosto-Dan Date: Fri, 12 Jun 2026 01:45:01 +0300 Subject: [PATCH 04/11] Add chapter "Review" about Vortex simulation methods. Replace and rename some chapters. --- Daniil_Pravkin/Daniil_Pravkin_report.tex | 55 ++++++++++++++++-------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/Daniil_Pravkin/Daniil_Pravkin_report.tex b/Daniil_Pravkin/Daniil_Pravkin_report.tex index c94f6d3..93bd091 100644 --- a/Daniil_Pravkin/Daniil_Pravkin_report.tex +++ b/Daniil_Pravkin/Daniil_Pravkin_report.tex @@ -43,7 +43,7 @@ \begin{flushright} Группа: \enquote{25.Б73-мм} - Кафедра: Кафедра системного программирования + Кафедра: системного программирования Научный руководитель: Григорьев Семён Вячеславович @@ -53,17 +53,37 @@ \end{flushright} -\section{Постановка задачи} +\section{Введение} + +Vortex --- это проект с открытым исходным кодом, предназначенный для поддержки вычислений на графических процессорах (GPGPU). Он реализован на основе расширений системы команд RISC-V ISA и предусматривает возможность аппаратной конфигурации. -Vortex --- это проект с открытым исходным кодом, предназначенный для поддержки вычислений на графических процессорах (GPGPU). Он реализован на основе расширений системы команд RISC-V ISA и предусматривает возможность аппаратной конфигурации. Целью данной работы является получение навыков работы с FPGA-стеком. +Vortex использует модель исполнения SIMT (Single Instruction Multiple Threads)\footnote{Информация из документации Vortex о микроархитектуре на сайте github.com (\url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md}) (27.04.2026)}, в рамках которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads) --- наименьших единиц вычисления, выполняемых параллельно, --- и варпов (warps), которые представляют собой набор потоков, исполняющих одну и ту же инструкцию. За счёт этого достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц (\url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html}) (29.05.2026)}. Результаты работы необходимы для дальнейшей работы с Vortex: сборка Vortex, оценка потребления ресурсов конфигурации, сравнение различных конфигураций. -\section{Описание предлагаемого решения} +\section{Постановка задачи} -Vortex использует модель исполнения SIMT (Single Instruction Multiple Threads)\footnote{Информация из документации Vortex о микроархитектуре на сайте github.com (\url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md}) (27.04.2026)}, в рамках которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads) --- наименьших единиц вычисления, выполняемых параллельно, --- и варпов (warps), которые представляют собой набор потоков, исполняющих одну и ту же инструкцию. За счёт этого достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц (\url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html}) (29.05.2026)}. +Целью данной работы является получение навыков работы с FPGA-стеком. + +Для достижения цели требуется решить следующие задачи: +\begin{enumerate} + \item Выполнить обзор способов симуляции Vortex. + \item Провести эксперименты с функцией умножения матриц при различных конфигурациях Vortex. +\end{enumerate} -С целью получения навыков работы с Vortex был проведён эксперимент по измерению масштабируемости функции умножения матриц. Реализация решения осуществлялась в среде Docker-контейнера с применением симулятора SimX, поскольку он обеспечивает достаточно высокую потактовую точность, затрачивая при этом меньше времени на выполнение, чем RTL-симулятор. +\section{Обзор} + +Перед проведением экспериментов необходимо было выбрать способ симуляции Vortex: RTL-симуляцию или Cycle-Approximate-симуляцию. + +Первый вариант осуществляется при помощи Verilator --- симулятора, преобразующего код на Verilog HDL, в однопоточный или многопоточный код на C++/SystemC. В таком подходе моделируется каждый отдельный сигнал, триггер и логический элемент. Вследствие чего данный метод довольно точен, но при этом он затрачивает много времени, поэтому он используется для проверки корректности взаимодействия программы и архитектуры Vortex. + +Второй вариант осуществляется при помощи SimX --- симулятора Vortex, написанного на C++. Он является потактовым, то есть воспроизводит поведение микроархитектуры с точностью до такта (содержимое кэша, состояние счётчиков, загрузка конвейера). Поэтому данный метод чуть менее точен, но более быстр по сравнению с RTL-симуляцией. + +Таким образом, было принято решение использовать в эксперименте симулятор SimX. + +\section{Описание предлагаемого решения} + +С целью получения навыков работы с Vortex был проведён эксперимент по измерению масштабируемости функции умножения матриц. Реализация решения осуществлялась в среде Docker-контейнера с применением симулятора SimX. \section{Эксперименты} @@ -89,10 +109,7 @@ \subsection*{Проведение эксперимента} \subsection*{Результаты и анализ} В результате поиска аппаратной конфигурации (табл. \ref{tab:optimal_for_8}) наиболее оптимальной при восьми ядрах оказалась следующая: clusters=1, warps=8, threads=64, l2cache, l3cache. -По результатам тестов по измерению масштабируемости (рис. \ref{figure:sgemm_graph}), при увеличении числа ядер от 1 до 16 количество тактов уменьшается, а при cores=16 достигает наименьшего значения. В диапазоне от 17 до 31 в ходе экспериментов возникали ошибки, свидетельствовавшие о неудачной попытке разделить задачу между всеми вычислительными блоками. Например, при запуске конфигурации с 18~ядрами в итоговой статистике для двух из них были выведены отрицательные значения количества выполненных инструкций и затраченных тактов. При дальнейшем увеличении числа ядер (начиная с 32) наблюдался рост количества тактов. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу вычислительных блоков, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество превышает значение, полученное при 16 ядрах. Таким образом, для умножения матриц 512x512 при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) наименьшее количество тактов достигается при использовании 16 ядер. - - -\begin{table} +\begin{table}[h] \centering \begin{tabular}{| c|c|c |} \hline @@ -101,16 +118,16 @@ \subsection*{Результаты и анализ} 2 & 16 & 43,0 \\ 2 & 32 & 22,8 \\ 2 & 64 & 13,8 \\ - + 4 & 16 & 30,3 \\ 4 & 32 & 16,4 \\ 4 & 64 & 13,7 \\ - + 8 & 16 & 30,6 \\ 8 & 32 & 18,8 \\ \rowcolor{lightgray} 8 & 64 & 13,6 \\ - + 16 & 16 & 33,4 \\ 16 & 32 & 18,8 \\ 16 & 64 & 14,2 \\ @@ -119,11 +136,7 @@ \subsection*{Результаты и анализ} \caption{\label{tab:optimal_for_8} Число тактов, затраченных на выполнение алгоритма умножения матриц размера 512x512 при фиксированных параметрах (cores=8, clusters=1, l2cache, l3cache) и различных значениях числа потоков и групп потоков. Выделенная строка --- конфигурация, при которой затрачено наименьшее число тактов.} \end{table} -\begin{figure} - \centering - \includegraphics[width=0.8\linewidth]{sgemm_graph.png} - \caption{\label{figure:sgemm_graph} Изменение числа тактов, затраченных на выполнение алгоритма умножения матриц при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) и различных значениях количества ядер.} -\end{figure} +По результатам тестов по измерению масштабируемости (рис. \ref{figure:sgemm_graph}), при увеличении числа ядер от 1 до 16 количество тактов уменьшается, а при cores=16 достигает наименьшего значения. В диапазоне от 17 до 31 в ходе экспериментов возникали ошибки, свидетельствовавшие о неудачной попытке разделить задачу между всеми вычислительными блоками. Например, при запуске конфигурации с 18~ядрами в итоговой статистике для двух из них были выведены отрицательные значения количества выполненных инструкций и затраченных тактов. При дальнейшем увеличении числа ядер (начиная с 32) наблюдался рост количества тактов. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу вычислительных блоков, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество превышает значение, полученное при 16 ядрах. Таким образом, для умножения матриц 512x512 при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) наименьшее количество тактов достигается при использовании 16 ядер. \section{Заключение} @@ -136,4 +149,10 @@ \section{Заключение} Техническая документация: \url{https://github.com/Prosto-Dan/vortex_practice_1_year} . +\begin{figure} + \centering + \includegraphics[width=0.8\linewidth]{sgemm_graph.png} + \caption{\label{figure:sgemm_graph} Изменение числа тактов, затраченных на выполнение алгоритма умножения матриц при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) и различных значениях количества ядер.} +\end{figure} + \end{document} From c39f0dee862d4cc4b0ff88db3e43eed38376022c Mon Sep 17 00:00:00 2001 From: Prosto-Dan Date: Fri, 12 Jun 2026 15:09:58 +0300 Subject: [PATCH 05/11] Correction report Change sgemm_graph.png to sgemm_graph.pdf --- Daniil_Pravkin/Daniil_Pravkin_report.tex | 32 +++++++++++------------ Daniil_Pravkin/sgemm_graph.pdf | Bin 0 -> 21773 bytes Daniil_Pravkin/sgemm_graph.png | Bin 27683 -> 0 bytes 3 files changed, 16 insertions(+), 16 deletions(-) create mode 100644 Daniil_Pravkin/sgemm_graph.pdf delete mode 100644 Daniil_Pravkin/sgemm_graph.png diff --git a/Daniil_Pravkin/Daniil_Pravkin_report.tex b/Daniil_Pravkin/Daniil_Pravkin_report.tex index 93bd091..5361c53 100644 --- a/Daniil_Pravkin/Daniil_Pravkin_report.tex +++ b/Daniil_Pravkin/Daniil_Pravkin_report.tex @@ -55,7 +55,7 @@ \section{Введение} -Vortex --- это проект с открытым исходным кодом, предназначенный для поддержки вычислений на графических процессорах (GPGPU). Он реализован на основе расширений системы команд RISC-V ISA и предусматривает возможность аппаратной конфигурации. +Vortex~--- это проект с открытым исходным кодом, предназначенный для поддержки вычислений на графических процессорах (GPGPU). Он реализован на основе расширений системы команд RISC-V ISA и предусматривает возможность аппаратной конфигурации. Vortex использует модель исполнения SIMT (Single Instruction Multiple Threads)\footnote{Информация из документации Vortex о микроархитектуре на сайте github.com (\url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md}) (27.04.2026)}, в рамках которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads) --- наименьших единиц вычисления, выполняемых параллельно, --- и варпов (warps), которые представляют собой набор потоков, исполняющих одну и ту же инструкцию. За счёт этого достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц (\url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html}) (29.05.2026)}. @@ -67,19 +67,19 @@ \section{Постановка задачи} Для достижения цели требуется решить следующие задачи: \begin{enumerate} - \item Выполнить обзор способов симуляции Vortex. - \item Провести эксперименты с функцией умножения матриц при различных конфигурациях Vortex. + \item Выполнить обзор способов симуляции Vortex + \item Провести эксперименты с функцией умножения матриц при различных конфигурациях Vortex \end{enumerate} \section{Обзор} Перед проведением экспериментов необходимо было выбрать способ симуляции Vortex: RTL-симуляцию или Cycle-Approximate-симуляцию. -Первый вариант осуществляется при помощи Verilator --- симулятора, преобразующего код на Verilog HDL, в однопоточный или многопоточный код на C++/SystemC. В таком подходе моделируется каждый отдельный сигнал, триггер и логический элемент. Вследствие чего данный метод довольно точен, но при этом он затрачивает много времени, поэтому он используется для проверки корректности взаимодействия программы и архитектуры Vortex. +Первый вариант осуществляется при помощи Verilator~--- симулятора, преобразующего код на Verilog HDL в однопоточный или многопоточный код на C++/SystemC. В таком подходе моделируется каждый отдельный сигнал, триггер и логический элемент. Вследствие чего данный метод довольно точен, но при этом он затрачивает много времени. -Второй вариант осуществляется при помощи SimX --- симулятора Vortex, написанного на C++. Он является потактовым, то есть воспроизводит поведение микроархитектуры с точностью до такта (содержимое кэша, состояние счётчиков, загрузка конвейера). Поэтому данный метод чуть менее точен, но более быстр по сравнению с RTL-симуляцией. +Второй вариант осуществляется при помощи SimX~--- симулятора Vortex, написанного на C++. Он является потактовым, то есть воспроизводит поведение микроархитектуры с точностью до такта (содержимое кэша, состояние счётчиков, загрузка конвейера). Поэтому данный метод чуть менее точен, но более быстр по сравнению с RTL-симуляцией. -Таким образом, было принято решение использовать в эксперименте симулятор SimX. +Таким образом, было принято решение использовать в экспериментах симулятор SimX. \section{Описание предлагаемого решения} @@ -91,15 +91,15 @@ \subsection*{Цель} Проанализировать масштабируемость функции умножения матриц при увеличении количества ядер и фиксированном объёме входных данных. \subsection*{Входные данные} -Для эксперимента была выбрана матрица размера 512x512 с целью получения более реалистичной производительности. Для алгоритма требуется память для двух перемножаемых матриц и одной итоговой, следовательно, объём трёх матриц данного размера --- 3~МиБ, что превышает объём общей памяти (Local Memory) (128 КиБ), L1-кэша (16~КиБ), L2-кэша (1~МиБ) и L3-кэша (2~МиБ)\footnote{Объёмы общей памяти и l1/l2/l3-кэшей взяты со страниц Vortex на сайте github.com (объём общей памяти: \url{https://github.com/vortexgpgpu/vortex/blob/master/hw/rtl/mem/VX_local_mem.sv} оъёмы кэшей: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/simulation.md}) (26.04.2026)}; следовательно, программа будет больше взаимодействовать с основной памятью. +Для экспериментов была выбрана матрица размера 512x512 с целью получения более реалистичной производительности. Для алгоритма требуется память для двух перемножаемых матриц и одной итоговой, при этом каждый элемент матрицы имеет тип float\footnote{Информация из реализации функции sgemm в Vortex (\url{https://github.com/vortexgpgpu/vortex/blob/master/tests/regression/sgemm/common.h}) (12.06.2026)}, следовательно, объём трёх матриц данного размера~--- 3~МиБ, что превышает объём общей памяти (Local Memory) (128 КиБ), L1-кэша (16~КиБ), L2-кэша (1~МиБ) и L3-кэша (2~МиБ)\footnote{Объёмы общей памяти и l1/l2/l3-кэшей взяты со страниц Vortex на сайте github.com (объём общей памяти: \url{https://github.com/vortexgpgpu/vortex/blob/master/hw/rtl/mem/VX_local_mem.sv} оъёмы кэшей: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/simulation.md}) (26.04.2026)}; следовательно, программа будет больше взаимодействовать с основной памятью. -\subsection*{Проведение эксперимента} +\subsection*{Проведение экспериментов} Порядок выполнения тестов: \begin{enumerate} - \item Отключение графической оболочки, для повышения скорости симуляции. - \item Запуск Docker-контейнера. - \item Запуск тестов и запись результатов. + \item Отключение графической оболочки, для повышения скорости симуляции + \item Запуск Docker-контейнера + \item Запуск тестов и запись результатов \end{enumerate} Сперва надо было подобрать оптимальную конфигурацию для более реалистичной производительности. Подбор производился при cores=8, потому что большее количество ядер порождает большую нагрузку на память, то есть более реалистичную производительность. @@ -107,7 +107,7 @@ \subsection*{Проведение эксперимента} Далее были выполнены тесты с оптимальной конфигурацией, но изменяемым количеством ядер. Значения количества ядер кратны степеням двойки, чтобы обеспечить более равномерное распределение нагрузки между ядрами, так как размер матрицы тоже кратен степени двойки. \subsection*{Результаты и анализ} -В результате поиска аппаратной конфигурации (табл. \ref{tab:optimal_for_8}) наиболее оптимальной при восьми ядрах оказалась следующая: clusters=1, warps=8, threads=64, l2cache, l3cache. +В результате поиска аппаратной конфигурации (табл.~\ref{tab:optimal_for_8}) наиболее оптимальной при восьми ядрах оказалась следующая: clusters=1, warps=8, threads=64, l2cache, l3cache. \begin{table}[h] \centering @@ -133,10 +133,10 @@ \subsection*{Результаты и анализ} 16 & 64 & 14,2 \\ \hline \end{tabular} -\caption{\label{tab:optimal_for_8} Число тактов, затраченных на выполнение алгоритма умножения матриц размера 512x512 при фиксированных параметрах (cores=8, clusters=1, l2cache, l3cache) и различных значениях числа потоков и групп потоков. Выделенная строка --- конфигурация, при которой затрачено наименьшее число тактов.} +\caption{\label{tab:optimal_for_8} Число тактов, затраченных на выполнение алгоритма умножения матриц размера 512x512 при фиксированных параметрах (cores=8, clusters=1, l2cache, l3cache) и различных значениях числа потоков и групп потоков. Выделенная строка~--- конфигурация, при которой затрачено наименьшее число тактов.} \end{table} -По результатам тестов по измерению масштабируемости (рис. \ref{figure:sgemm_graph}), при увеличении числа ядер от 1 до 16 количество тактов уменьшается, а при cores=16 достигает наименьшего значения. В диапазоне от 17 до 31 в ходе экспериментов возникали ошибки, свидетельствовавшие о неудачной попытке разделить задачу между всеми вычислительными блоками. Например, при запуске конфигурации с 18~ядрами в итоговой статистике для двух из них были выведены отрицательные значения количества выполненных инструкций и затраченных тактов. При дальнейшем увеличении числа ядер (начиная с 32) наблюдался рост количества тактов. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу вычислительных блоков, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество превышает значение, полученное при 16 ядрах. Таким образом, для умножения матриц 512x512 при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) наименьшее количество тактов достигается при использовании 16 ядер. +По результатам тестов по измерению масштабируемости (рис.~\ref{figure:sgemm_graph}), при увеличении числа ядер от 1 до 16 количество тактов уменьшается, а при cores=16 достигает наименьшего значения. В диапазоне от 17 до 31 в ходе экспериментов возникали ошибки, свидетельствовавшие о неудачной попытке разделить задачу между всеми вычислительными блоками. Например, при запуске конфигурации с 18~ядрами в итоговой статистике для двух из них были выведены отрицательные значения количества выполненных инструкций и затраченных тактов. При дальнейшем увеличении числа ядер (начиная с 32) наблюдался рост количества тактов. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу вычислительных блоков, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество превышает значение, полученное при 16~ядрах. Таким образом, для умножения матриц 512x512 при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) наименьшее количество тактов достигается при использовании 16~ядер. \section{Заключение} @@ -147,11 +147,11 @@ \section{Заключение} \item Проанализирована масштабируемость функции умножения матриц. \end{itemize} -Техническая документация: \url{https://github.com/Prosto-Dan/vortex_practice_1_year} . +Техническая документация: \url{https://github.com/Prosto-Dan/vortex_practice_1_year/blob/main/docs/analyze.md} . \begin{figure} \centering - \includegraphics[width=0.8\linewidth]{sgemm_graph.png} + \includegraphics[width=0.8\linewidth]{sgemm_graph.pdf} \caption{\label{figure:sgemm_graph} Изменение числа тактов, затраченных на выполнение алгоритма умножения матриц при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) и различных значениях количества ядер.} \end{figure} diff --git a/Daniil_Pravkin/sgemm_graph.pdf b/Daniil_Pravkin/sgemm_graph.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e9a197e5dc99359083a959111a927cd58278a0c0 GIT binary patch literal 21773 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%0A9p@b(!`i*-H>t+oeiFLYg zrStqhNc_VTaeo7!2K)L@IIUuk_A`d(drT>H6Th0f#_^N{y+5@>L;hhS`Q0xM=orHY zI>|A?IKQu5MPjz+0?ROT=u+BGy#_h%$DH^0RlN)Uu<^`MwsY&qw9;+=7cyZ%2@1|D(`%-UeF&&}c6u%rnLyN%0%UGw~R*il3^CB^v@43>hCOu9q zV!o!)ls2d!+%m_XsXypvY<`cfYhV6I`c`)X10443NmmhXwT%1ZBV0LM(pBYjCY*sS z?qQ9|;T8kow>g>M+rn{zTa~t@X3~BO8sWMqmyMZDvyo>`N~RyhTrYh)$e+|T(fvZL zU?A(_>kxg;O+2wuwTCUWSdHqBDJq(2>OAzmWJF`jb?pmB6>l}I?8lfE?@Yafyu%(- zg<}+iE80ia(da*Nbbo3TL=OIF69CTQ3{DaU7nr@nLTCN%G3~UdntSS7P%m$3tDbqh z^2_!JfkVc|Z(~o76i=zvvPi}7Od+M(wHiC4Mg%1922Yuq;ZLydW=qU+4eVn;_K7AA z=L{W@bk%>OsI59b8EsIRG%{lnzTYfTHsH?346&VE)g>1P9EKbR{1$lH-L)->gGtIg zsH*K=#I{-2`onh}u!e^uy$+7N5b-|$3w_0>B5p>?v%5(>Xtyed`C7iKIvryind{@D zVte%Ik<^3_PiQqYlPNzbQaMzk-);p^uS#e;_P|BEb{!4>Bggy4M1leF`#%mkWX1BJ z!(cX5LP!>GeSl>7{-cG^U6yFYO^zF~H+G%AabnYk$1PiC*WvtMyP*gW==&qYN&O#lzGH*?l4^`XWO~CmgtRMR&X)r5`>ms&8?TUn)10^Thzw4o1{|N z+(M^2G~>aBKqkn$zGK7#oc|YA)2p5|Sl}56RU5jr*CdY@+xxBL&7d!C)Ajh%rJo8r zH#a>Iq*zDrmCoPy4IJ`sc*p4C=}Eb1C+C3w#uq2!lQNkLb$;W{73i4ffu3MvtXciF$|DR@aM{B{#;{M<2Q2lwP|rQ);6^ẐxQ@3 z?n3>Ymj=mXVr$$t57}G}J6X*=76Y^1$tEJ#QLMzY)vZ&o0CRo+F^(rE-wfT>FT9zy zEo{?9BZ=+3r6o=pk?g)-vc6QX__TW1Ye>7 z%7S)@_W)ag1keU3VQ_fj6%RldSO{|g@DfX9Am|8!h!sNNp?YWliGXkv5HteF0woBL z0^vQrD~+gZfcqdS2wZ_esi8J8pw2JA5r|0yWIs?#5KxHt8%-jt2@(w=u~ePdCs1{e zs4?IB><6i(8({EDBmiiMh;f0q0-QtL37NricP(E5x75p8B2qvD%n%Tps6NOJe$Zbw z5TY>wO3?EUDiBj}I5qLzcLI0-gj`OLAuQPdWCy<{qOO5mKsK==5$yr8iRDDJmG3qI z*~7{N>6-WqXh62HoFK`u;J4ja2w4T$z&Z&JP(Vbx0Ba?7MOwCr5~X)fF7V36#%G+s|s-r1<)hn z12p-fAwLI9_CN74KsUso4axj2jAojs;izvXrFea-1cSQgRfMEMiD!}%^B=Db9z>ooe z{{N-|&60nh0tPG5K!9)a8==8C1>n;E=0y&mFaN-cJebe^Kt&M(B{tT+1quZ#>k+l3a{oCBA8fzUsnm>G=Ezc zbQwT){!UlWLi~GOfoT^2P@%d%2R?D6FVBL1cff;(iGtM;{QDVfLl8mQfB2w?TOxuU zoVAk$?Y}|M(}a~t!P+$>3B;x@){Kp7MelS^44b`__=)dXymIJ!C48HT$jRNpYITq5 z;m*!OW^QL}TdN3B*L~lMeL0HEE)Y>Dn2eNNXy@Eo^n~!~NRa}g!*JOx+GBGBGLQKy zO8YjXkRz^<2?#c)#1G8NRXt#(Qc|&AyRm{g=~wBOJ|ZWs?qmyr;=vjW>5KSLH6MT| zC(iBPKfwZggrAiaz=zQw{QpjX(f4%qAhbwyps`;GfeOUNoIKnWq0iOrRFp)*kytob z(?JLnjYbN?QG#%|pwNn5_V=>0rv`pAoEqS^zyAR{!hq3l5Bre^t$@%U%>8>F_>muE z#=qntBrwp_zd8>x%2j!g6TBu5QrhZrz#IHE4?L}*2Zy5|x8aw%a3JsMHUJ79oOG`# z2hIP#)J5PW;H&fC5-4c;{-qpT0s$PvRe8Xl14H!Ja(EOT7|XAD;P(e>>LM{9j=Q=X ztgfHe##uK<27E1Q@fc%K^ALv>ro$KjZ*f zUSpHsR{&slwW=Iqt=%IK=r#5Njs&5__SZHL_%-7QkXvIf2;@5YLqeOIRrHYS@P|S} zYt66ig5MXc9&ZRVVvS7#G1ke$0N~~-dT0sATl}>R3>@-KR^=hr>J)=nGgc8`@3Y$e z5ZJYLj{y6m)olRlTUnRjW#!~*=SBQ%slHR79hi$@;(8t)(2_!2&DGrPJ-|5u@c}H) Y-UKTz0&&^~lRF+o&Cjo-txWxY01vQWNB{r; literal 0 HcmV?d00001 diff --git a/Daniil_Pravkin/sgemm_graph.png b/Daniil_Pravkin/sgemm_graph.png deleted file mode 100644 index 679dbcc966bbb7edc57fbfdf3b477ab660cb4ba8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27683 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 Date: Sun, 14 Jun 2026 02:12:28 +0300 Subject: [PATCH 06/11] Correction of report --- Daniil_Pravkin/Daniil_Pravkin_report.tex | 100 +++++++++++------------ 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/Daniil_Pravkin/Daniil_Pravkin_report.tex b/Daniil_Pravkin/Daniil_Pravkin_report.tex index 5361c53..409cfde 100644 --- a/Daniil_Pravkin/Daniil_Pravkin_report.tex +++ b/Daniil_Pravkin/Daniil_Pravkin_report.tex @@ -55,9 +55,9 @@ \section{Введение} -Vortex~--- это проект с открытым исходным кодом, предназначенный для поддержки вычислений на графических процессорах (GPGPU). Он реализован на основе расширений системы команд RISC-V ISA и предусматривает возможность аппаратной конфигурации. +Графический процессор (GPU)~--- вычислительный блок, созданный для ускорения параллельных операций при 3D-рендеринге в реальном времени. Большинство его транзисторов используется для обработки данных, в то время как в центральном процессоре (CPU) значительная часть задействована для кэширования и управления потоками. За счёт этого графический процессор обеспечивает более высокую скорость обработки команд и пропускную способность памяти, чем CPU, при аналогичных цене и мощности~\footnote{CUDA Pragramming Guide, URL: \url{https://docs.nvidia.com/cuda/archive/13.1.0/cuda-programming-guide/01-introduction/introduction.html#} (дата обращения: 13.06.2026)}. -Vortex использует модель исполнения SIMT (Single Instruction Multiple Threads)\footnote{Информация из документации Vortex о микроархитектуре на сайте github.com (\url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md}) (27.04.2026)}, в рамках которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads) --- наименьших единиц вычисления, выполняемых параллельно, --- и варпов (warps), которые представляют собой набор потоков, исполняющих одну и ту же инструкцию. За счёт этого достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц (\url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html}) (29.05.2026)}. +Vortex~--- это проект с открытым исходным кодом, предназначенный для поддержки вычислений на графических процессорах (GPGPU). Он реализован на основе расширений системы команд RISC-V ISA и предусматривает возможность аппаратной конфигурации. Vortex использует модель исполнения SIMT (Single Instruction Multiple Threads)~\footnote{Документация Vortex о микроархитектуре, URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md} (дата обращения: 27.04.2026)}, в рамках которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads)~--- наименьших единиц вычисления, выполняемых параллельно,~--- и варпов (warps), которые представляют собой набор потоков, исполняющих одну и ту же инструкцию. За счёт этого достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)~\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц, URL: \url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html} (дата обращения: 29.05.2026)}. Результаты работы необходимы для дальнейшей работы с Vortex: сборка Vortex, оценка потребления ресурсов конфигурации, сравнение различных конфигураций. @@ -67,15 +67,15 @@ \section{Постановка задачи} Для достижения цели требуется решить следующие задачи: \begin{enumerate} - \item Выполнить обзор способов симуляции Vortex - \item Провести эксперименты с функцией умножения матриц при различных конфигурациях Vortex + \item выполнить обзор способов симуляции Vortex; + \item провести эксперименты с функцией умножения матриц при различных конфигурациях Vortex. \end{enumerate} \section{Обзор} Перед проведением экспериментов необходимо было выбрать способ симуляции Vortex: RTL-симуляцию или Cycle-Approximate-симуляцию. -Первый вариант осуществляется при помощи Verilator~--- симулятора, преобразующего код на Verilog HDL в однопоточный или многопоточный код на C++/SystemC. В таком подходе моделируется каждый отдельный сигнал, триггер и логический элемент. Вследствие чего данный метод довольно точен, но при этом он затрачивает много времени. +Первый вариант осуществляется при помощи Verilator~--- симулятора, преобразующего код на Verilog HDL в однопоточный или многопоточный код на C++/SystemC. В таком подходе моделируется каждый отдельный сигнал, триггер и логический элемент. Вследствие чего данный метод довольно точен, но при этом затрачивает много времени. Второй вариант осуществляется при помощи SimX~--- симулятора Vortex, написанного на C++. Он является потактовым, то есть воспроизводит поведение микроархитектуры с точностью до такта (содержимое кэша, состояние счётчиков, загрузка конвейера). Поэтому данный метод чуть менее точен, но более быстр по сравнению с RTL-симуляцией. @@ -87,72 +87,72 @@ \section{Описание предлагаемого решения} \section{Эксперименты} -\subsection*{Цель} +\subsection{Цель} Проанализировать масштабируемость функции умножения матриц при увеличении количества ядер и фиксированном объёме входных данных. -\subsection*{Входные данные} -Для экспериментов была выбрана матрица размера 512x512 с целью получения более реалистичной производительности. Для алгоритма требуется память для двух перемножаемых матриц и одной итоговой, при этом каждый элемент матрицы имеет тип float\footnote{Информация из реализации функции sgemm в Vortex (\url{https://github.com/vortexgpgpu/vortex/blob/master/tests/regression/sgemm/common.h}) (12.06.2026)}, следовательно, объём трёх матриц данного размера~--- 3~МиБ, что превышает объём общей памяти (Local Memory) (128 КиБ), L1-кэша (16~КиБ), L2-кэша (1~МиБ) и L3-кэша (2~МиБ)\footnote{Объёмы общей памяти и l1/l2/l3-кэшей взяты со страниц Vortex на сайте github.com (объём общей памяти: \url{https://github.com/vortexgpgpu/vortex/blob/master/hw/rtl/mem/VX_local_mem.sv} оъёмы кэшей: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/simulation.md}) (26.04.2026)}; следовательно, программа будет больше взаимодействовать с основной памятью. +\subsection{Условия эксперимента} +Для экспериментов была выбрана матрица размера $512\times512$ с целью получения более реалистичной производительности. Для алгоритма требуется память для двух перемножаемых матриц и одной итоговой, при этом каждый элемент матрицы имеет тип float~\footnote{Информация из реализации функции sgemm в Vortex, URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/tests/regression/sgemm/common.h} (дата обращения: 12.06.2026)}, следовательно, объём трёх матриц данного размера~--- 3~МиБ, что превышает объём общей памяти (Local Memory) (128 КиБ), L1-кэша (16~КиБ), L2-кэша (1~МиБ) и L3-кэша (2~МиБ)\footnote{Объёмы общей памяти и l1/l2/l3-кэшей взяты из документации Vortex (объём общей памяти: URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/hw/rtl/mem/VX_local_mem.sv} оъёмы кэшей: URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/simulation.md}) (дата обращения: 26.04.2026)}; следовательно, программа будет больше взаимодействовать с основной памятью. -\subsection*{Проведение экспериментов} - -Порядок выполнения тестов: -\begin{enumerate} - \item Отключение графической оболочки, для повышения скорости симуляции - \item Запуск Docker-контейнера - \item Запуск тестов и запись результатов -\end{enumerate} +\samepage{ + Порядок выполнения тестов: + \begin{enumerate} + \item отключение графической оболочки, для повышения скорости симуляции; + \item запуск Docker-контейнера; + \item запуск тестов и запись результатов. + \end{enumerate} +} Сперва надо было подобрать оптимальную конфигурацию для более реалистичной производительности. Подбор производился при cores=8, потому что большее количество ядер порождает большую нагрузку на память, то есть более реалистичную производительность. Далее были выполнены тесты с оптимальной конфигурацией, но изменяемым количеством ядер. Значения количества ядер кратны степеням двойки, чтобы обеспечить более равномерное распределение нагрузки между ядрами, так как размер матрицы тоже кратен степени двойки. -\subsection*{Результаты и анализ} +\subsection{Результаты} + В результате поиска аппаратной конфигурации (табл.~\ref{tab:optimal_for_8}) наиболее оптимальной при восьми ядрах оказалась следующая: clusters=1, warps=8, threads=64, l2cache, l3cache. +По результатам тестов по измерению масштабируемости (рис.~\ref{figure:sgemm_graph}), при увеличении числа ядер от 1 до 16 количество тактов уменьшается, а при cores=16 достигает наименьшего значения. В диапазоне от 17 до 31 в ходе экспериментов возникали ошибки, свидетельствовавшие о неудачной попытке разделить задачу между всеми вычислительными блоками. Например, при запуске конфигурации с 18~ядрами в итоговой статистике для двух из них были выведены отрицательные значения количества выполненных инструкций и затраченных тактов. При дальнейшем увеличении числа ядер (начиная с 32) наблюдался рост количества тактов. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу вычислительных блоков, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество превышает значение, полученное при 16~ядрах. Таким образом, для умножения матриц $512\times512$ при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) наименьшее количество тактов достигается при использовании 16~ядер. + \begin{table}[h] -\centering -\begin{tabular}{| c|c|c |} - \hline - Кол-во групп потоков & Кол-во потоков & Кол-во тактов (млн.) \\ - \hline - 2 & 16 & 43,0 \\ - 2 & 32 & 22,8 \\ - 2 & 64 & 13,8 \\ - - 4 & 16 & 30,3 \\ - 4 & 32 & 16,4 \\ - 4 & 64 & 13,7 \\ - - 8 & 16 & 30,6 \\ - 8 & 32 & 18,8 \\ - \rowcolor{lightgray} - 8 & 64 & 13,6 \\ - - 16 & 16 & 33,4 \\ - 16 & 32 & 18,8 \\ - 16 & 64 & 14,2 \\ - \hline -\end{tabular} -\caption{\label{tab:optimal_for_8} Число тактов, затраченных на выполнение алгоритма умножения матриц размера 512x512 при фиксированных параметрах (cores=8, clusters=1, l2cache, l3cache) и различных значениях числа потоков и групп потоков. Выделенная строка~--- конфигурация, при которой затрачено наименьшее число тактов.} + \centering + \caption{\label{tab:optimal_for_8} Число тактов, затраченных на выполнение алгоритма умножения матриц размера $512\times512$ при фиксированных параметрах (cores=8, clusters=1, l2cache, l3cache) и различных значениях числа потоков и групп потоков. Выделенная строка~--- конфигурация, при которой затрачено наименьшее число тактов.} + \begin{tabular}{r r r} + \hline + \multicolumn{1}{c}{Кол-во групп потоков} & \multicolumn{1}{c}{Кол-во потоков} & \multicolumn{1}{c}{Кол-во тактов (млн.)} \\ \hline + 2 & 16 & 43,0 \\ \hline + 2 & 32 & 22,8 \\ \hline + 2 & 64 & 13,8 \\ \hline + + 4 & 16 & 30,3 \\ \hline + 4 & 32 & 16,4 \\ \hline + 4 & 64 & 13,7 \\ \hline + + 8 & 16 & 30,6 \\ \hline + 8 & 32 & 18,8 \\ \hline + \rowcolor{lightgray} + 8 & 64 & 13,6 \\ \hline + + 16 & 16 & 33,4 \\ \hline + 16 & 32 & 18,8 \\ \hline + 16 & 64 & 14,2 \\ \hline + \end{tabular} \end{table} -По результатам тестов по измерению масштабируемости (рис.~\ref{figure:sgemm_graph}), при увеличении числа ядер от 1 до 16 количество тактов уменьшается, а при cores=16 достигает наименьшего значения. В диапазоне от 17 до 31 в ходе экспериментов возникали ошибки, свидетельствовавшие о неудачной попытке разделить задачу между всеми вычислительными блоками. Например, при запуске конфигурации с 18~ядрами в итоговой статистике для двух из них были выведены отрицательные значения количества выполненных инструкций и затраченных тактов. При дальнейшем увеличении числа ядер (начиная с 32) наблюдался рост количества тактов. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу вычислительных блоков, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество превышает значение, полученное при 16~ядрах. Таким образом, для умножения матриц 512x512 при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) наименьшее количество тактов достигается при использовании 16~ядер. +\begin{figure} + \centering + \includegraphics[width=0.8\linewidth]{sgemm_graph.pdf} + \caption{\label{figure:sgemm_graph} Изменение числа тактов, затраченных на выполнение алгоритма умножения матриц при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) и различных значениях количества ядер.} +\end{figure} + \section{Заключение} В ходе выполнения работы получены следующие результаты: \begin{itemize} - \item Произведено сравнение количества тактов, затрачиваемых различными конфигурациями Vortex при выполнении функции умножения матриц. - \item Проанализирована масштабируемость функции умножения матриц. + \item произведено сравнение количества тактов, затрачиваемых различными конфигурациями Vortex при выполнении функции умножения матриц; + \item проанализирована масштабируемость функции умножения матриц. \end{itemize} Техническая документация: \url{https://github.com/Prosto-Dan/vortex_practice_1_year/blob/main/docs/analyze.md} . -\begin{figure} - \centering - \includegraphics[width=0.8\linewidth]{sgemm_graph.pdf} - \caption{\label{figure:sgemm_graph} Изменение числа тактов, затраченных на выполнение алгоритма умножения матриц при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) и различных значениях количества ядер.} -\end{figure} - \end{document} From 1488c941a291792103b8aaea4c08c505982b1103 Mon Sep 17 00:00:00 2001 From: Prosto-Dan Date: Sun, 14 Jun 2026 09:52:29 +0300 Subject: [PATCH 07/11] Correction of report. --- Daniil_Pravkin/Daniil_Pravkin_report.tex | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Daniil_Pravkin/Daniil_Pravkin_report.tex b/Daniil_Pravkin/Daniil_Pravkin_report.tex index 409cfde..d2d5d35 100644 --- a/Daniil_Pravkin/Daniil_Pravkin_report.tex +++ b/Daniil_Pravkin/Daniil_Pravkin_report.tex @@ -55,9 +55,9 @@ \section{Введение} -Графический процессор (GPU)~--- вычислительный блок, созданный для ускорения параллельных операций при 3D-рендеринге в реальном времени. Большинство его транзисторов используется для обработки данных, в то время как в центральном процессоре (CPU) значительная часть задействована для кэширования и управления потоками. За счёт этого графический процессор обеспечивает более высокую скорость обработки команд и пропускную способность памяти, чем CPU, при аналогичных цене и мощности~\footnote{CUDA Pragramming Guide, URL: \url{https://docs.nvidia.com/cuda/archive/13.1.0/cuda-programming-guide/01-introduction/introduction.html#} (дата обращения: 13.06.2026)}. +Графический процессор (GPU)~--- вычислительный блок, созданный для ускорения параллельных операций при 3D-рендеринге в реальном времени. Большинство его транзисторов используется для обработки данных, в то время как в центральном процессоре (CPU) значительная часть задействована для кэширования и управления потоками. За счёт этого графический процессор обеспечивает более высокую скорость обработки команд и пропускную способность памяти, чем CPU, при аналогичных цене и мощности~\footnote{CUDA Pragramming Guide, URL: \url{https://docs.nvidia.com/cuda/archive/13.1.0/cuda-programming-guide/01-introduction/introduction.html#} (дата обращения: 13.06.2026).}. -Vortex~--- это проект с открытым исходным кодом, предназначенный для поддержки вычислений на графических процессорах (GPGPU). Он реализован на основе расширений системы команд RISC-V ISA и предусматривает возможность аппаратной конфигурации. Vortex использует модель исполнения SIMT (Single Instruction Multiple Threads)~\footnote{Документация Vortex о микроархитектуре, URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md} (дата обращения: 27.04.2026)}, в рамках которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads)~--- наименьших единиц вычисления, выполняемых параллельно,~--- и варпов (warps), которые представляют собой набор потоков, исполняющих одну и ту же инструкцию. За счёт этого достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)~\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц, URL: \url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html} (дата обращения: 29.05.2026)}. +Vortex~--- это проект с открытым исходным кодом, предназначенный для поддержки вычислений на графических процессорах (GPGPU). Он реализован на основе расширений системы команд RISC-V ISA и предусматривает возможность аппаратной конфигурации. Vortex использует модель исполнения SIMT (Single Instruction Multiple Threads)~\footnote{Документация Vortex о микроархитектуре, URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md} (дата обращения: 27.04.2026).}, в рамках которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads)~--- наименьших единиц вычисления, выполняемых параллельно,~--- и варпов (warps), которые представляют собой набор потоков, исполняющих одну и ту же инструкцию. За счёт этого достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)~\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц, URL: \url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html} (дата обращения: 29.05.2026).}. Результаты работы необходимы для дальнейшей работы с Vortex: сборка Vortex, оценка потребления ресурсов конфигурации, сравнение различных конфигураций. @@ -91,7 +91,15 @@ \subsection{Цель} Проанализировать масштабируемость функции умножения матриц при увеличении количества ядер и фиксированном объёме входных данных. \subsection{Условия эксперимента} -Для экспериментов была выбрана матрица размера $512\times512$ с целью получения более реалистичной производительности. Для алгоритма требуется память для двух перемножаемых матриц и одной итоговой, при этом каждый элемент матрицы имеет тип float~\footnote{Информация из реализации функции sgemm в Vortex, URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/tests/regression/sgemm/common.h} (дата обращения: 12.06.2026)}, следовательно, объём трёх матриц данного размера~--- 3~МиБ, что превышает объём общей памяти (Local Memory) (128 КиБ), L1-кэша (16~КиБ), L2-кэша (1~МиБ) и L3-кэша (2~МиБ)\footnote{Объёмы общей памяти и l1/l2/l3-кэшей взяты из документации Vortex (объём общей памяти: URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/hw/rtl/mem/VX_local_mem.sv} оъёмы кэшей: URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/simulation.md}) (дата обращения: 26.04.2026)}; следовательно, программа будет больше взаимодействовать с основной памятью. +\samepage{ + Во время эксперимента использовались: + \begin{itemize} + \item Vortex 2.2 + \item Docker Engine 29.5.2 + \end{itemize} +} + +Для экспериментов была выбрана матрица размера $512\times512$ с целью получения более реалистичной производительности. Для алгоритма требуется память для двух перемножаемых матриц и одной итоговой, при этом каждый элемент матрицы имеет тип float~\footnote{Информация из реализации функции sgemm в Vortex, URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/tests/regression/sgemm/common.h} (дата обращения: 12.06.2026).}, следовательно, объём трёх матриц данного размера~--- 3~МиБ, что превышает объём общей памяти (Local Memory) (128 КиБ), L1-кэша (16~КиБ), L2-кэша (1~МиБ) и L3-кэша (2~МиБ)~\footnote{Объёмы общей памяти и l1/l2/l3-кэшей взяты из документации Vortex (объём общей памяти: URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/hw/rtl/mem/VX_local_mem.sv}, оъёмы кэшей: URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/simulation.md}) (дата обращения: 26.04.2026).}; следовательно, программа будет больше взаимодействовать с основной памятью. \samepage{ Порядок выполнения тестов: @@ -153,6 +161,6 @@ \section{Заключение} \item проанализирована масштабируемость функции умножения матриц. \end{itemize} -Техническая документация: \url{https://github.com/Prosto-Dan/vortex_practice_1_year/blob/main/docs/analyze.md} . +Техническая документация: \url{https://github.com/Prosto-Dan/vortex_practice_1_year/blob/main/docs/analyze.md}. \end{document} From d2e29616daab0bdbab6d6616f9572c78084b7495 Mon Sep 17 00:00:00 2001 From: Prosto-Dan Date: Sun, 14 Jun 2026 10:20:12 +0300 Subject: [PATCH 08/11] Fix errors in build. --- Daniil_Pravkin/Daniil_Pravkin_report.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Daniil_Pravkin/Daniil_Pravkin_report.tex b/Daniil_Pravkin/Daniil_Pravkin_report.tex index d2d5d35..fc48328 100644 --- a/Daniil_Pravkin/Daniil_Pravkin_report.tex +++ b/Daniil_Pravkin/Daniil_Pravkin_report.tex @@ -55,7 +55,7 @@ \section{Введение} -Графический процессор (GPU)~--- вычислительный блок, созданный для ускорения параллельных операций при 3D-рендеринге в реальном времени. Большинство его транзисторов используется для обработки данных, в то время как в центральном процессоре (CPU) значительная часть задействована для кэширования и управления потоками. За счёт этого графический процессор обеспечивает более высокую скорость обработки команд и пропускную способность памяти, чем CPU, при аналогичных цене и мощности~\footnote{CUDA Pragramming Guide, URL: \url{https://docs.nvidia.com/cuda/archive/13.1.0/cuda-programming-guide/01-introduction/introduction.html#} (дата обращения: 13.06.2026).}. +Графический процессор (GPU)~--- вычислительный блок, созданный для ускорения параллельных операций при 3D-рендеринге в реальном времени. Большинство его транзисторов используется для обработки данных, в то время как в центральном процессоре (CPU) значительная часть задействована для кэширования и управления потоками. За счёт этого GPU обеспечивает более высокую скорость обработки команд и пропускную способность памяти, чем CPU, при аналогичных цене и мощности~\footnote{Информация взята из CUDA Pragramming Guide, URL: \url{https://docs.nvidia.com/cuda/archive/13.1.0/cuda-programming-guide/01-introduction/introduction.html} (дата обращения: 13.06.2026).}. Vortex~--- это проект с открытым исходным кодом, предназначенный для поддержки вычислений на графических процессорах (GPGPU). Он реализован на основе расширений системы команд RISC-V ISA и предусматривает возможность аппаратной конфигурации. Vortex использует модель исполнения SIMT (Single Instruction Multiple Threads)~\footnote{Документация Vortex о микроархитектуре, URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/microarchitecture.md} (дата обращения: 27.04.2026).}, в рамках которой одна и та же инструкция выполняется над разными данными. Это достигается при помощи потоков (threads)~--- наименьших единиц вычисления, выполняемых параллельно,~--- и варпов (warps), которые представляют собой набор потоков, исполняющих одну и ту же инструкцию. За счёт этого достигается распараллеливание выполнения задачи. Одной из задач, выполняемой при помощи такой модели исполнения, является умножение матриц (например, в графических процессорах от компании NVIDIA)~\footnote{В архитектуре CUDA, использующей SIMT, также есть функция умножения матриц, URL: \url{https://docs.nvidia.com/cutlass/latest/media/docs/cpp/efficient_gemm.html} (дата обращения: 29.05.2026).}. From 0607cab727dba4b94c658fbaf98b473ea2520402 Mon Sep 17 00:00:00 2001 From: Daniil_Pravkin Date: Sun, 14 Jun 2026 17:10:36 +0300 Subject: [PATCH 09/11] Correction of report. --- Daniil_Pravkin/Daniil_Pravkin_report.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Daniil_Pravkin/Daniil_Pravkin_report.tex b/Daniil_Pravkin/Daniil_Pravkin_report.tex index fc48328..056b9ec 100644 --- a/Daniil_Pravkin/Daniil_Pravkin_report.tex +++ b/Daniil_Pravkin/Daniil_Pravkin_report.tex @@ -65,7 +65,7 @@ \section{Постановка задачи} Целью данной работы является получение навыков работы с FPGA-стеком. -Для достижения цели требуется решить следующие задачи: +Для достижения цели требуется решить следующие задачи. \begin{enumerate} \item выполнить обзор способов симуляции Vortex; \item провести эксперименты с функцией умножения матриц при различных конфигурациях Vortex. @@ -154,7 +154,7 @@ \subsection{Результаты} \section{Заключение} -В ходе выполнения работы получены следующие результаты: +В ходе выполнения работы получены следующие результаты. \begin{itemize} \item произведено сравнение количества тактов, затрачиваемых различными конфигурациями Vortex при выполнении функции умножения матриц; From 3c38de04b00a3c22623e6d6f328cf3f03b06f7ba Mon Sep 17 00:00:00 2001 From: Prosto-Dan Date: Mon, 15 Jun 2026 16:53:45 +0300 Subject: [PATCH 10/11] Correction of report. --- Daniil_Pravkin/Daniil_Pravkin_report.tex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Daniil_Pravkin/Daniil_Pravkin_report.tex b/Daniil_Pravkin/Daniil_Pravkin_report.tex index fc48328..da5306d 100644 --- a/Daniil_Pravkin/Daniil_Pravkin_report.tex +++ b/Daniil_Pravkin/Daniil_Pravkin_report.tex @@ -79,7 +79,7 @@ \section{Обзор} Второй вариант осуществляется при помощи SimX~--- симулятора Vortex, написанного на C++. Он является потактовым, то есть воспроизводит поведение микроархитектуры с точностью до такта (содержимое кэша, состояние счётчиков, загрузка конвейера). Поэтому данный метод чуть менее точен, но более быстр по сравнению с RTL-симуляцией. -Таким образом, было принято решение использовать в экспериментах симулятор SimX. +Поскольку эксперимент предполагает многократный запуск тестов и анализ общего поведения функции, а не получение абсолютно точного значения затраченных тактов, для сокращения временных затрат было принято решение использовать в экспериментах симулятор SimX. \section{Описание предлагаемого решения} @@ -102,7 +102,7 @@ \subsection{Условия эксперимента} Для экспериментов была выбрана матрица размера $512\times512$ с целью получения более реалистичной производительности. Для алгоритма требуется память для двух перемножаемых матриц и одной итоговой, при этом каждый элемент матрицы имеет тип float~\footnote{Информация из реализации функции sgemm в Vortex, URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/tests/regression/sgemm/common.h} (дата обращения: 12.06.2026).}, следовательно, объём трёх матриц данного размера~--- 3~МиБ, что превышает объём общей памяти (Local Memory) (128 КиБ), L1-кэша (16~КиБ), L2-кэша (1~МиБ) и L3-кэша (2~МиБ)~\footnote{Объёмы общей памяти и l1/l2/l3-кэшей взяты из документации Vortex (объём общей памяти: URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/hw/rtl/mem/VX_local_mem.sv}, оъёмы кэшей: URL: \url{https://github.com/vortexgpgpu/vortex/blob/master/docs/simulation.md}) (дата обращения: 26.04.2026).}; следовательно, программа будет больше взаимодействовать с основной памятью. \samepage{ - Порядок выполнения тестов: + Порядок выполнения экспериментов: \begin{enumerate} \item отключение графической оболочки, для повышения скорости симуляции; \item запуск Docker-контейнера; @@ -112,13 +112,13 @@ \subsection{Условия эксперимента} Сперва надо было подобрать оптимальную конфигурацию для более реалистичной производительности. Подбор производился при cores=8, потому что большее количество ядер порождает большую нагрузку на память, то есть более реалистичную производительность. -Далее были выполнены тесты с оптимальной конфигурацией, но изменяемым количеством ядер. Значения количества ядер кратны степеням двойки, чтобы обеспечить более равномерное распределение нагрузки между ядрами, так как размер матрицы тоже кратен степени двойки. +Далее запускались тесты с оптимальной конфигурацией, но изменяемым количеством ядер. Значения количества ядер кратны степеням двойки, чтобы обеспечить более равномерное распределение нагрузки между ядрами, так как размер матрицы тоже кратен степени двойки. \subsection{Результаты} В результате поиска аппаратной конфигурации (табл.~\ref{tab:optimal_for_8}) наиболее оптимальной при восьми ядрах оказалась следующая: clusters=1, warps=8, threads=64, l2cache, l3cache. -По результатам тестов по измерению масштабируемости (рис.~\ref{figure:sgemm_graph}), при увеличении числа ядер от 1 до 16 количество тактов уменьшается, а при cores=16 достигает наименьшего значения. В диапазоне от 17 до 31 в ходе экспериментов возникали ошибки, свидетельствовавшие о неудачной попытке разделить задачу между всеми вычислительными блоками. Например, при запуске конфигурации с 18~ядрами в итоговой статистике для двух из них были выведены отрицательные значения количества выполненных инструкций и затраченных тактов. При дальнейшем увеличении числа ядер (начиная с 32) наблюдался рост количества тактов. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу вычислительных блоков, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество превышает значение, полученное при 16~ядрах. Таким образом, для умножения матриц $512\times512$ при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) наименьшее количество тактов достигается при использовании 16~ядер. +По результатам эксперимента по измерению масштабируемости (рис.~\ref{figure:sgemm_graph}), при увеличении числа ядер от 1 до 16 количество тактов уменьшается, а при cores=16 достигает наименьшего значения. В диапазоне от 17 до 31 в ходе экспериментов возникали ошибки, свидетельствовавшие о неудачной попытке разделить задачу между всеми вычислительными блоками. Например, при запуске конфигурации с 18~ядрами в итоговой статистике для двух из них были выведены отрицательные значения количества выполненных инструкций и затраченных тактов. При дальнейшем увеличении числа ядер (начиная с 32) наблюдался рост количества тактов. Это свидетельствует о накладных расходах, затрачиваемых на корректную работу вычислительных блоков, в том числе для обеспечения параллельного выполнения, вследствие чего суммарное количество превышает значение, полученное при 16~ядрах. Таким образом, для умножения матриц $512\times512$ при фиксированных параметрах (clusters=1, warps=8, threads=64, l2cache, l3cache) наименьшее количество тактов достигается при использовании 16~ядер. \begin{table}[h] \centering From 74eec8948ae7df338848b07cf4b1adcac2ae6039 Mon Sep 17 00:00:00 2001 From: Prosto-Dan Date: Mon, 15 Jun 2026 17:02:41 +0300 Subject: [PATCH 11/11] Correction of report. --- Daniil_Pravkin/Daniil_Pravkin_report.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Daniil_Pravkin/Daniil_Pravkin_report.tex b/Daniil_Pravkin/Daniil_Pravkin_report.tex index 928fb21..da5306d 100644 --- a/Daniil_Pravkin/Daniil_Pravkin_report.tex +++ b/Daniil_Pravkin/Daniil_Pravkin_report.tex @@ -65,7 +65,7 @@ \section{Постановка задачи} Целью данной работы является получение навыков работы с FPGA-стеком. -Для достижения цели требуется решить следующие задачи. +Для достижения цели требуется решить следующие задачи: \begin{enumerate} \item выполнить обзор способов симуляции Vortex; \item провести эксперименты с функцией умножения матриц при различных конфигурациях Vortex. @@ -154,7 +154,7 @@ \subsection{Результаты} \section{Заключение} -В ходе выполнения работы получены следующие результаты. +В ходе выполнения работы получены следующие результаты: \begin{itemize} \item произведено сравнение количества тактов, затрачиваемых различными конфигурациями Vortex при выполнении функции умножения матриц;