From f27a299d90a44f421ac4ec6f27b304a51293112d Mon Sep 17 00:00:00 2001 From: Brulevich-Nikita Date: Fri, 12 Jun 2026 18:15:22 +0300 Subject: [PATCH 01/12] add Brulevich Nikita report --- Nikita_Brulevich/Nikita_Brulevich_report.tex | 290 ++++++++++++++++++ Nikita_Brulevich/images/memory_comparison.png | Bin 0 -> 48528 bytes Nikita_Brulevich/images/time_comparison.png | Bin 0 -> 47379 bytes main.tex | 3 + 4 files changed, 293 insertions(+) create mode 100644 Nikita_Brulevich/Nikita_Brulevich_report.tex create mode 100644 Nikita_Brulevich/images/memory_comparison.png create mode 100644 Nikita_Brulevich/images/time_comparison.png diff --git a/Nikita_Brulevich/Nikita_Brulevich_report.tex b/Nikita_Brulevich/Nikita_Brulevich_report.tex new file mode 100644 index 0000000..972ac98 --- /dev/null +++ b/Nikita_Brulevich/Nikita_Brulevich_report.tex @@ -0,0 +1,290 @@ +% Данный файл распространяется под лицензией 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{float} +\usepackage{graphicx} + +\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{booktabs} +\usepackage{multirow} + +\title{LaMaGraph: Разреженные матрицы на F\#} + +\author{Брулевич Никита Петрович} + +\date{} + +\begin{document} + +\maketitle + +\begin{flushright} + Группа: \emph{2025.Б-73-мм} + + Кафедра: \emph{кафедра системного программирования} + + Научный руководитель: \emph{Григорьев Семён Вячеславович} + + Номер семестра практики: \emph{2} +\end{flushright} + +\section{Постановка задачи} + +Работа выполняется в рамках проекта \textbf{LamaGraph} (Lambdas, Matrices and Graphs), нацеленного на разработку прототипа быстрого вычислителя для разреженной линейной алгебры, реализованного в функциональной парадигме программирования на языке F\#. + +Одной из ключевых частей проекта является библиотека \textbf{QTreeFSharp} для работы с разреженными матрицами и векторами на языке F\#, реализованная на деревьях квадрантов (quadtree). + +\textbf{Целью работы} является реализация и оптимизация следующих операций над разреженными матрицами и векторами: +\begin{itemize} + \item Редукция (свёртка) строк и столбцов матриц -- \texttt{reduceRows}, \texttt{reduceCols} + \item Срез (slice) векторов и матриц + \item Произведение Кронекера (kroneckerProduct) + \item Преобразование каждого ненулевого элемента матрицы (map) +\end{itemize} + +Данные операции необходимы для реализации графовых алгоритмов и оптимизации работы матричных алгоритмов в рамках прототипа вычислителя LamaGraph. + +\section{Описание предлагаемого решения} + +\subsection{Структуры данных} + +Разреженные векторы реализованы на бинарном дереве (\texttt{btree}), где листья содержат \texttt{UserValue} или \texttt{Dummy}. Размер дерева округляется до ближайшей степени двойки. + +Разреженные матрицы реализованы на дереве квадрантов (\texttt{qtree}) с четырьмя подузлами (NW, NE, SW, SE), что позволяет рекурсивно делить матрицу на квадранты. + +\subsection{Реализованные операции} + +\begin{itemize} + \item \texttt{reduceRows}, \texttt{reduceCols} -- свёртка матрицы в вектор с использованием заданной бинарной операции по строкам и по столбцам соответственно + \item \texttt{slice} -- выделение подматрицы/подвектора по заданным границам + \item \texttt{kroneckerProduct} -- произведение Кронекера двух матриц + \item \texttt{map} -- применение функции к каждому ненулевому элементу матрицы +\end{itemize} + +Также была изменена сигнатура функции fromCoordinateList в Matrix.fs и Vector.fs, добавлена валидация аргументов. + +Дополнительно проведено сравнение двух способов реализации \texttt{reduceCols}: +\begin{enumerate} + \item Прямой обход по столбцам (оригинальная реализация) + \item Транспонирование матрицы с последующей свёрткой по строкам (альтернативный подход с учётом уже реализованной в проекте функции transpose). +\end{enumerate} + +\subsection{Тестирование} + +Для каждой из новых реализованных функций написаны Unit-тесты: +\begin{itemize} + \item \texttt{Vector.slice} -- 11 тестов + \item \texttt{Matrix.map} -- 6 тестов + \item \texttt{Matrix.slice} -- 22 теста + \item \texttt{Matrix.reduceRows} -- 7 тестов + \item \texttt{Matrix.reduceCols} -- 7 тестов + \item \texttt{Matrix.kroneckerProduct} -- 13 тестов +\end{itemize} +А также добавлены отсутствующие тесты на уже имевшиеся функции - 17 тестов. + +\section{Эксперименты} + +\subsection{Методология} + +Бенчмарки проводились с использованием \texttt{BenchmarkDotNet v0.15.8} на виртуальной машине с 4GB RAM. Для каждого теста измерялись среднее время выполнения (Mean), стандартное отклонение (StdDev) и объём аллоцированной памяти (Allocated). + +Использовались синтетические матрицы следующих типов: +\begin{itemize} + \item \textbf{Sparse} --- разреженные матрицы со случайными значениями (плотность 1\%, 5\%, 10\%) + \item \textbf{DenseUniform} --- плотные матрицы с единичными значениями (оптимальный случай) + \item \textbf{DenseRandom} --- плотные матрицы со случайными значениями (использовалось в экспериментах над reduceCols и reduceRows) +\end{itemize} + +\subsection{Результаты} + +\subsubsection{ReduceRows и ReduceCols} + +\begin{table}[H] +\centering +\caption{Результаты Reduce бенчмарков} +\begin{tabular}{lccc} +\toprule +Метод & Размер & Время (Mean) & Аллокации \\ +\midrule +\multicolumn{4}{c}{\textbf{Sparse (разреженные, случайные)}} \\ +\midrule +ReduceRows\_SparseSmall & 32×32 & 64.2 μs & 67.6 KB \\ +ReduceCols\_SparseSmall & 32×32 & 65.7 μs & 72.7 KB \\ +ReduceRows\_SparseMedium & 256×256 & 1.73 ms & 1.27 MB \\ +ReduceCols\_SparseMedium & 256×256 & 1.87 ms & 1.35 MB \\ +ReduceRows\_SparseLarge & 1024×1024 & 9.31 ms & 4.59 MB \\ +ReduceCols\_SparseLarge & 1024×1024 & 10.16 ms & 4.97 MB \\ +\midrule +\multicolumn{4}{c}{\textbf{DenseUniform (плотные, все 1.0)}} \\ +\midrule +ReduceRows\_DenseUniformSmall & 32×32 & 255.6 μs & 308 KB \\ +ReduceCols\_DenseUniformSmall & 32×32 & 264.5 μs & 313 KB \\ +ReduceRows\_DenseUniformMedium & 256×256 & 56.7 ms & 17.6 MB \\ +ReduceCols\_DenseUniformMedium & 256×256 & 72.4 ms & 17.6 MB \\ +ReduceRows\_DenseUniformLarge & 1024×1024 & 856 ms & 276 MB \\ +ReduceCols\_DenseUniformLarge & 1024×1024 & 1137 ms & 277 MB \\ +\midrule +\multicolumn{4}{c}{\textbf{DenseRandom (плотные, случайные)}} \\ +\midrule +ReduceRows\_DenseRandomSmall & 32×32 & 277.6 μs & 308 KB \\ +ReduceCols\_DenseRandomSmall & 32×32 & 293.2 μs & 312 KB \\ +ReduceRows\_DenseRandomMedium & 256×256 & 77.9 ms & 17.6 MB \\ +ReduceCols\_DenseRandomMedium & 256×256 & 74.6 ms & 17.6 MB \\ +ReduceRows\_DenseRandomLarge & 1024×1024 & 1072 ms & 276 MB \\ +ReduceCols\_DenseRandomLarge & 1024×1024 & 1106 ms & 277 MB \\ +\bottomrule +\end{tabular} +\end{table} + +\subsubsection{Сравнение reduceCols и reduceCols как transpose + reduceRows} + +\begin{table}[H] +\centering +\small +\caption{Сравнение прямой реализации reduceCols и реализации через транспонирование} +\begin{tabular}{lcccccc} +\toprule +\multirow{2}{*}{Метод} & \multirow{2}{*}{Размер} & \multicolumn{2}{c}{Время (Mean)} & \multicolumn{2}{c}{Аллокации} & \multirow{2}{*}{Разница по времени} \\ +\cline{3-6} +& & Оригинал & Транспонирование & Оригинал & Транспонирование & \\ +\midrule +ReduceCols\_SparseSmall & 32×32 & 66.5 μs & 78.5 μs & 72.7 KB & 75.0 KB & +18\% \\ +ReduceCols\_DenseSmall & 32×32 & 265 μs & 261 μs & 313 KB & 310 KB & -1.5\% \\ +ReduceCols\_SparseMedium & 256×256 & 1.84 ms & 2.78 ms & 1.35 MB & 1.40 MB & +51\% \\ +ReduceCols\_DenseMedium & 256×256 & 64.8 ms & 57.5 ms & 17.6 MB & 17.6 MB & \textbf{-11\%} \\ +ReduceCols\_SparseLarge & 1024×1024 & 9.89 ms & 19.5 ms & 4.97 MB & 5.10 MB & +97\% \\ +ReduceCols\_DenseLarge & 1024×1024 & 1.14 s & 0.89 s & 277 MB & 277 MB & \textbf{-22\%} \\ +\bottomrule +\end{tabular} +\end{table} + +\begin{figure}[H] +\centering +\includegraphics[width=0.85\textwidth]{images/time_comparison.png} +\caption{Сравнение времени выполнения оригинального reduceCols и реализации через транспонирование} +\label{fig:reducecols_time} +\end{figure} + +\begin{figure}[H] +\centering +\includegraphics[width=0.85\textwidth]{images/memory_comparison.png} +\caption{Сравнение аллокаций памяти оригинального reduceCols и реализации через транспонирование} +\label{fig:reducecols_memory} +\end{figure} + +На плотных матрицах реализация через транспонирование оказывается быстрее на 10-22\% благодаря лучшей кэш-локальности. На разреженных матрицах, напротив, прямой обход по столбцам оказывается быстрее на 18-97\%. + +\subsubsection{Slice для векторов} + +\begin{table}[H] +\centering +\caption{Результаты VectorSlice (срез середины)} +\begin{tabular}{lccc} +\toprule +Метод & Размер & Время (Mean) & Аллокации \\ +\midrule +Slice\_SparseSmall & 32 & 2.6 μs & 3.8 KB \\ +Slice\_DenseSmall & 32 & 2.8 μs & 4.5 KB \\ +Slice\_SparseMedium & 256 & 29.7 μs & 42.5 KB \\ +Slice\_DenseMedium & 256 & 31.6 μs & 46.3 KB \\ +Slice\_SparseLarge & 1024 & 181 μs & 212 KB \\ +Slice\_DenseLarge & 1024 & 178 μs & 216 KB \\ +\bottomrule +\end{tabular} +\end{table} + +\subsubsection{Slice для матриц} + +\begin{table}[H] +\centering +\caption{Результаты MatrixSlice (срез середины)} +\begin{tabular}{lccc} +\toprule +Метод & Размер & Время (Mean) & Аллокации \\ +\midrule +MatrixSlice\_SparseSmall & 32×32 & 68.8 μs & 68 KB \\ +MatrixSlice\_DenseSmall & 32×32 & 53.3 μs & 77 KB \\ +MatrixSlice\_SparseMedium & 256×256 & 14.0 ms & 6.9 MB \\ +MatrixSlice\_DenseMedium & 256×256 & 15.0 ms & 7.2 MB \\ +MatrixSlice\_SparseLarge & 1024×1024 & 285 ms & 138 MB \\ +MatrixSlice\_DenseLarge & 1024×1024 & 302 ms & 139 MB \\ +\bottomrule +\end{tabular} +\end{table} + +\subsubsection{Произведение Кронекера} + +\begin{table}[H] +\centering +\caption{Результаты KroneckerProduct} +\begin{tabular}{lccc} +\toprule +Метод & Исходный размер & Время (Mean) & Аллокации \\ +\midrule +Kronecker\_SparseSmall & 8×8 & 92.1 μs & 86 KB \\ +Kronecker\_DenseSmall & 8×8 & 2.31 ms & 1.5 MB \\ +Kronecker\_SparseMedium & 16×16 & 1.20 ms & 229 KB \\ +Kronecker\_DenseMedium & 16×16 & 114 ms & 31 MB \\ +Kronecker\_SparseLarge & 32×32 & 6.22 ms & 112 KB \\ +Kronecker\_DenseLarge & 32×32 & 1.29 s & 576 MB \\ +\bottomrule +\end{tabular} +\end{table} + +\subsection{Выводы из экспериментов} + +\begin{enumerate} + \item \textbf{Редукция матриц (reduceRows, reduceCols)}: разреженные матрицы демонстрируют преимущество над плотными во всех размерах. На малых матрицах (32×32) выигрыш составляет 3-4 раза (64-66 μs против 256-293 μs), на средних (256×256) -- 30-40 раз (1.7-1.9 ms против 56-78 ms), на больших (1024×1024) -- до 120 раз (9-10 ms против 856-1137 ms). Аллокации памяти также отличаются в 4, 15 и 60 раз соответственно. Результаты времени выполнения для плотных матриц с единичными и случайными значениями (DenseUniform и DenseRandom) близки, разница не превышает 25\%, разница объёма аллоцированной памяти - не более 2\%. + + \item \textbf{Сравнение реализаций reduceCols}: транспонирование эффективнее на плотных матрицах (ускорение растёт с размером: 1.5\%, 11\%, 22\%), но проигрывает на разреженных (замедление 18\%, 51\%, 97\%). Это объясняется лучшей кэш-локальностью при последовательном обходе строк после транспонирования. + + \item \textbf{Срез (slice)}: на всех размерах производительность для разреженных и плотных матриц/векторов остаётся сопоставимой (разница не превышает 10-15\%). + + \item \textbf{Произведение Кронекера}: выигрыш разреженных матриц над плотными растёт с размером. Для матриц 8×8 разреженная быстрее в 25 раз (92 μs против 2.3 ms), для 16×16 -- в 95 раз (1.2 ms против 114 ms), для 32×32 -- в 200 раз (6.2 ms против 1.29 с). Аллокации памяти различаются ещё сильнее: 86 KB против 1.5 MB (8×8), 229 KB против 31 MB (16×16), 112 KB против 576 MB (32×32). Соотношение по памяти достигает 5000 раз на максимальном размере. +\end{enumerate} + +\section{Заключение} +В ходе выполнения работы получены следующие результаты: + +\begin{itemize} + \item Реализованы и оптимизированы операции \texttt{reduceRows}, \texttt{reduceCols}, \texttt{slice}, \texttt{kroneckerProduct}, \texttt{map} для разреженных матриц и векторов. + \item Проведено сравнение двух подходов к реализации \texttt{reduceCols}, показавшее преимущество транспонирования на плотных матрицах. + \item Выполнены бенчмарки для реализованных функций на плотных и разреженных векторах и матрицах разного размера. + \item Полученные результаты задокументированы и могут быть использованы для дальнейшей оптимизации графовых алгоритмов и работы с матрицами. +\end{itemize} + +\section{Источники} +\begin{thebibliography}{99} +\bibitem{qtreefsharp} Исходный код проекта QTreeFSharp. URL: \url{https://github.com/Lamagraph/QTreeFSharp} + +\bibitem{benchmarkdotnet} Официальная документация инструмента профилирования BenchmarkDotNet. URL: \url{https://benchmarkdotnet.org/} + +\bibitem{fsharpdocs} Документация по языку F\#. URL: \url{https://learn.microsoft.com/ru-ru/dotnet/fsharp/} +\end{thebibliography} + +\section{Репозиторий} +\url{https://github.com/Brulevich-Nikita/QTreeFSharp1} + +\end{document} diff --git a/Nikita_Brulevich/images/memory_comparison.png b/Nikita_Brulevich/images/memory_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..9310693368612ca3a083741dbe391a99bf848ec5 GIT binary patch literal 48528 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 X|GC^=#+X994TUqxr_)Xv-Tc1*6X|+_ literal 0 HcmV?d00001 diff --git a/Nikita_Brulevich/images/time_comparison.png b/Nikita_Brulevich/images/time_comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..0ae046af4619b635b7ac0c5f2ed0949da623066b GIT binary patch literal 47379 zcmeFa2UwKZwk?Y7R=c$kZBdkHXjHODMuLiff(Vi`3L+UKOSap9fuKmv2nCWQ78w-* z2}O|+iXb`XOcCB(RnXnvGe(on1OF1XlT^1;vbt~Qc-O{|Lhi2J19K}oa})iO z4u&?iCRUa_oZQ@;7uZi4+u1#^73Siy_~SP?t!#|A0xB_9@G3t&xUOMKK|%8i`e&C> zR3p4sp2v-ASCk)yPjv0`S82)LH)D0^(BG5~J^0(TD|BE(-(PX-c+-CJyJqkrgXR}@?j_yJcIJ1kTsbVs{)qZ+cL$;NZ^1Ew!*x&Zx|ilm z2|Lya5yRc;inWcVdaR~jj==|93HqQ-kt_@Qf&BSZ0rJ1k?+UOaf2Q!do|638{$C1q zkv_Y8<&R&xK7tkpKKA?sYlS|dPsY%ZKcoKDZa3+(N54P$k6w)972_j}grT9~%?M#W z=cS4KxI*&P)DILbwrVw`=@bTExO??+N3xxkRNP04))Wodg6;Q^Q>@ld>~2(G?Fu~1 zchpivMMbuNjr{gV*BtO zoAV;$OWzE9{U*h+iAo6-+?Di43@Uwa;vVa>mG(=k3r+F{K{^gE5+a?G9J)T-E$jPy zfXge)vVf&zDJPwyH9tCEY5S557h1KfB$ubU`Y-jY-lBIJc*ES|VQCcUbiX#3`^-|O zEq>3G?b>L<@JEZ(oYt2$T%{tGg_F606CcX-*A_;tM`AoH2CCkcHVeh%Z$G=sCooAl zp}nWE-}GPkP3!fy8%22^;LJP8SupZW-DxmjyleQayjWGG6(QH6)3L|Ry7{(rdAG|n zgU4!(-kic)mIsA>FWE|(7q8edlb`ORi<)kWEp+x<_m(EwXD6*ZF5&UHTbo3#2c^{6 znAOfDSWDqyq0zXvb8~f&XJ%_%ATi$DFX<6M>PpzV?Jg^TvFg?Mo_4)psHr-d3 zrt%D8umhMN-Rhb())9V!d6v3m{$O7@jh>y>UG5*dLNoAUM0WYmkh4|m>+|>^J4cHB zCheJqb|dwtR5eX7BJ^ngT(;$NnE19bD(^u%9O+_dH{NOyL%bEr%fiLR#x}lDg0UU0 z%OO%6IA>=T-zZqzU+JsY*hO(ZWI>!Nj=Q4ij2wFr+-gA~dZ{eCPV34+)*RlVfp@i` zd~94=Ii@PpOW7s&neOyHvBYJ6PCfg;tf$1yZsHqvN4Cik4$a^`D&x?h+K?kn3G(>g z2>vWeb4J>0PZi41&aLm%cI>iuip;$oE5*@jM?cw-Q&YoxTGOp@Z9(+n2ji>Q`{yZH zLgJ{Z8AY9g_x)r%*SN*|TCAy&>qUQscg-iQwUi^I!-&I$7)6GZp1ILtX`7ssR9$mK zUWD8CkX;pX&=*a!)T5#eHoL?wdY_Wt0N!O4BhWM+*2P__ivqCOyy! z-)h1?$(-KB5l~xd-FH}e2vF?Ka=%R zyAeKXn!&M?8!z_p^G{u&ArMnUrf>T_^Z%QAYqM)E24AocGVH+#FGUghmd-No6l~nv zMjKqPndrahJovOHquY60GD^&CZcUEA{nxdnNxCyqUe9guq5>sb8`Hy!RzjUS+ ztMF99BheT2_VCKV(wueMrBg<4`7zUY3eQi9HXpL<3LRDlgNBDqEY}7aWx2dBO&9Tq zi?7d=&BvZ1QXRh#-EFIDU4Ar2#Z1d0r$vO|zFgQ-E=HU<0=H%Q^NEYU7C21O%8PH< z)rJf4?4_ioE}Y1et(xA&{%SjRDM(qBtlp34WoimH<(p5kz;-!2UE0cA>M%>s8%s*= z^H;j{g4>{CKzfZSj7n_f`*C4A;}`=8TgBU=j-yB9R3R7*h5T%L1#OA+qB$A&k~-n> z_YS)Qg~WzoeI8-DzGWDg?ao?TnCiMDPFvvN*63I{T|%@p&nQ2Z0Xwm^P(C!Re|0#@ z7ljpg+X%MqXrWPTutv@A@BcW92Ht#gu^CHx3c(6T&a+>y3FL_N*xGzrw;LByPf2^y z+i)FLr<^!l%4E@z{UTD-Wr%e8DC$LW)EgNd#sBJU=!)V7YjVmjbXG;y6S)LSC;i3+ zkC3=t;jI}@@qu5=(etE;cDg-UaaBc`x0tS3J&U^AbslH^^_1tAh0&&YyouLd|IgxD0#CR zi}pgK>s-~t$(**nsI7G)k-4vDW)p3Woc2A)AY7XzAKEra?AdZp$sY>MfXGx?MkP*9qx~q~yot;jPNyz{RcVB0%FVkv!Vbix$?-`EIfBDvNBONwlgdU!IL0=me#&kF z%TM0(S+9n(U5w4O*q;QK zn|)m5;RA~>T0V<52nFld2MB?gbVFnHa4kec7Wru%l*02nljw#|ozk z%ornW;Ei8Fi2DM$D|~sY9q%5PT(k+hjD2a`Z^*Ck`|k&i}j5o*_ zAcl_pbCbMyM9}WNKdYy>+SkIC9|59+x**ya^d?8wtUJ-*JLG} z;#mu6S)LR^eCYpr#$sPhp&y4gmV442qu$;UPUL?e%gV|+SMQg2mF>jEdtdb<*eF|q850#J zzdxq3Y*tI5AC{3&t7FJxHW93npc3Wv5ncMWKF@*eRJ0;c?`>5NU+p11o@jqp9?Dk= zM~1R3yPPwoTjpxGqJntt*Q$R%PC zrPT;AOPHW|(tn68Ssn%ai@3XipW~mZm`8YQt~&YTlpVapo(tJPit=;GM1H({RLRE} z_9*z-o?I6IPW=dTc`~^RQsrwzQGel>h)i%fOAdO`olh)3{0O+rp=iGD61UC3*YW~2 zg9@(~@RqH)5k33aQeLxFj5U?G5uI2kj!_ptI&+!LirQeG-m1~t%)G5v_AH!j&m9+t zHbKI8NT7!i0!ce~vn^su2Vf~<8c$dH0U_DZule-#cmA>bWrxjM%x9O-|;?nhIOUpa$ z13__5R!)a2~7FFG%bz}~^!-M@7#E-5J~_w$4L=qujeWJ&w^eN->=UGDYuVR2u0 zom0=Km>5w?Utdi3z;R2k} z*2VzOZwl>kPTWAKsgmCIX0e5y$HwCNb%_g8S$Hw;wT^&!?J7o>i8r3lMF7n91*qv( zEuZW1MVm4WZrN3@NyO1sc2^g3koGS@y3Qu<47nYq$$Ji({Y1J>?;9g~U!B6?9f*_I zN))ODr;FzMAh^`|u3A9I=LYop4W2j6!xT=Pf`L=iN=G%EYc0I_TA#z?m~P0mAne(S zwP?S%&u&nm&KBbm#@Zp}L$7h^nvpke=a9$Nvd8dc%gwvOW=nFv5#$8As5vyxe<#J3 z=yfFl?Q%V7e^&_Z?Ac~YXt;#Z!itJVj>35^^-yHn-1Ed9EVaF+L zBR4=l^O=&bjxAb}pGIiZG1-FMA5xrqpVHWz#{x=eRsA|yFrJoCL2Gsmil6=uWd~oO zRQcQFxtqZxd@%t9UB;)qbl0GYHR$&i@Huiz@RTkTjOD^cZfQkx)kS!0$zrNA77tYw z3NJ(R@$OJa^5nu6S!wWfr?x6yR4pFX3a|XVZW%$qtX83qM-gq`Rw)^a@+0yGzH)CGmd5rlcySMeS`06w@$W&KR}fjK}HgKlE018*Ui zy$`$^y6TB@g<#MhYaf=tkCb?DZ z(e-mtt~TB0o=PM#4Zg0M2f!x9q_uw);$Qxk z9&yPji~ai`sZZ1Axec=Ey(nED10fG}*l9K^Hn6!X5Q`&xRKZqFl)2b>u{x#-hzoiuk(tY4L%%<> zSkF{sZkWf5M-8XQp3;K4&J>Hey9sqt;huvB@;j_ey{60;#G2l?is~Br&X(|T zKqs#PIkbj8a#C`vKr!U_TP4d=>;8(t`8d|pGd_Z+-M5H6K?{rQ&Z+Y~JpeFJx(_PD zD$fRf&RY#2q8+Pi-=Z=*k%g~V8&8i)?hv*cxgZ~<k}T=D6OLvwP&#AjSO6wek76yndfBRB5cY zDSQEp8yQr|-q)z_}ti>z30Pt zjBbTL?0d1g3MG4#r<1u?Th>TU{3$lGG`>Y4+~J_OyT_C~hOobOqy39pY<8TSmz^IX zhaB%Gmi1p1qi5hx+vtREh6`roIwx5Wa&yLk`I?{)j&u3|>_Li%o_dn9jKojzZdL`O z@q$1*jw@H<7#`jX}D&WBjE*Liga_OY@-ocTYDLL^Zi z5o#*B%kn*OdKS`JZa2Tlj~_!%?W&2f>M5E3*-S%EvV|?Z$S-Pnv?<}&HbD=*Zz$dm zCFKAoguShYf7ceOOUzH7Mm!-PH=$Ntm&wj32s1{J8$n-CtV?y8#>DW^@D|;}#g-@l z!%jhQ$K)hB4iJ@;toUxro#gglR!9<*1;$4+L5DVJ#uwTA1@I@;4R|#Bse%ED7O$5}6gQqOxwO z07iV=mb(N1-$e~frbEU4iw9c6QB6PU5ljpR>G6i1j-m7a)S{-xfVkYra24PleI*VG z{R#>BD4eCV2x3yjUOMyFK}O-$QbjYL59G8cEO$BT{e1kw$?k{!-hRuou=RW`y9&ym z{B&eaNHM25MI&o2m$&(QDz=*z*d33mI>*mHof}BPP-p&3%X?neeRZ&7{HDZ_O;m1( zGuhU1FV<{TB5 zFlyCKSQ{tZH0tO$p-+G=-y|mnYFXwBF4Rld{&-u)WHTLtCi1;o^XvGnb@_wlikFpc-#!dXy~)9R#i#A-C~4%u=`kQ!U~#8zB(2?$ zpgKq|c!3d!`fspb=`iVG7P%T}t-_G=ftPFj`kTW3hm9AWLekfZluq$i9PET@^NnxB z4}o@Rc6AW$1>6^t^~yz;JCC44$NLP*_lpNFO?=2Kij+*}duo`tKV|66582d@;_se7 zc^p7HL*UD0`8O_MpFi;q>+C<&231QDXBUB*HNKbESFrCn?A1$S5%UMh2SEYY$e(t} zsU{WOfJ*9Ef!^Ajn2O)8iL~cb-p&lheLSPm6L%pNP{e^wtAVd?8cIF3MxeU%q7z7S z*vK|%vU%|K^ON#7&)Q^TZY1qZ;C?YOKzwU}juud{v3kz$otz`93_<;iG$Oxaa@ zMBQ7T5LV2X(%3wP7|J@XnPZys(d}h;R=kDZ(Anhag2v)VAOgGjm)8w3&Z2ZSsZc=a z6{MA?o@Q%9hgqjSC&6uas;6&G2w_nFtCCNN>YR%ELp577PeK6VVtGnA+MuA9Ys2>R z;`}}y7WNRAyic?&?1@$zor?8u8DAOPzM`0j$G%rc8xf*Ou-O0P81=>0gqVPbn1WW! z;D*weOPEjF>yIRf>&}haLu7pa59O?Tw*-uTr8EC^{F8@ z^e$t~+b@a(U9#pkb?|ak3!>D8$?}>4ClKN9B|Hy02|3LTyiZHhZS2|w;zdZH7-48L zg;d0x_vDg^G*(5D$U0^Ls7w9MJnIGkXvR(Pa@oeG9`6aAdhM6^Idv!t{zuv&(b}M9 zC;;k;by=R`c3)pvAGE{KG*i^PTsRRVHcq;@YRQq-o2hwyFB_6nl2;%Q^#iBojThf? zz2W#%^lM&EEn3BkDtSM3qThaG144trsO;#%`;?U0`I8|%l*UPj$s%3hog0S>-mHEm zraYs!Q{Qpmf{4c25{zVGuKYe8iHR^kdfr6ZER+29tj`CmxhT1*_ zYMoc+^T3RLfxOKGLRp`;c({v!U5HqT6G7R ze|{8?G2~T(zITvkvH?(@QUTYC4R2_s^*hx%)|aCB`2_TxZ$ z+(+@ZdkMfrT@8y;{Fg5;j*OejPc~WmDZf$EQ_(GSn6$|YE`nUdZ9mp5OhoLfxLyYEclo1VKHx>Ht^9^$K)+Ipr+ zd}kP5O?$hRwtef-I7q(|uki}$KMt`j8^L9NWHqzZXE?5xiJb)^*y+#ZR#sM1 zQ>(lY@$ZdW8_n6eTD5I)MK=v!KvkNaC8`q9^5h;LF)(>& zKgwoNb~VzQu?&QYx;P;6!9Ev>jNBlmiIl2`vZaRa>>tfgi;+N5q3YDCVKi7ZYZ~{+ zeCGS7oHAw37k_R{@DG>-R{*)2wls`zW+c?~f@AMv^(z@1YsVG&+JTMNEyTkUM`D9_ z)!TEGz?#uY(_3FtR#yIkK%~6L>@_5P<8xYLrF}E8tC_WA1A&6@kR4l;;Tg;w4Fz5^ zjr&)zuz3b%Oz-9b<0lf{-`R*qPz0s3`IKqcjM`AvXVh>OHVfU#?{Gaq4m*z;4;KXB zGv6qFU_T$4lkH`A4IWY7Yl(vzBVywzS+^qW0srU#mBW@VW7+)v_M3}e7u)p2ky~P< zGvBtjl0|KsfeU?R7~hz>V{cFpX6>q$mid(Fmy>cb=S2F}_xS@V%Y4-I-0UM4frxu9%bEWx z!tJ=MP4LmYM8(WmxlmsG8Yo!eX&}6+Ljf|Zv4zyNUHj+{p%QagqZDfSFQ7Ia2055@ zl`msp+eGx}{uz~&Nub?lA>T+t_}2&dpdr(+W(7EoqljH|-5A%yw^%`T!4ngzb5Y5) z&m=L^!jr+_Yh@mgfcSuUo}!#tS$xSPrgQU8x+h-#Rkl%yn^N>ZHIpY;C0ff`IFi{$VEQkugZyPZhR8B}B+-Ey~$OTyZD!8gw#;%o#~R(A_H z*~(C}v=czB`$7%EPo)(COwqm!P+comX8ZdS6Cz*2@}v~e+=?~g*n5z~t?Zf$VCPDwYcTdE2d3Z;pHh2+@gz4}i33)|McH1uiqoVJauTjjQ_Wn=|82 z?2s@PvEk5Rl2Aksg3zbrJ0?3OuTXD@MWS_3yU_b!djBRbJQ^nmH0Hd*n=MGteV*d$ zy&@9gtv?Gr{IrLr_Q*#}FLOHVi}iKTYEyOe=8NvE5c)7>JBh8rLK(L54tO=ZjxA+2_3ll1~JArL< zs>{9in3DfF2p6nAAbLFn1#dn!UVjQ;fe+&BfPqsur=I*%&yZ?X8W1#w1)9|$^pLKd zmrml@&sDz>UYv_OjwGDnc2X^j)HV8e%rIZcD$c3`3|oPoQHTeQ1^JI;Pl(!FNGK`> zl{AN#1`?9fD!9PPL1w#%pRGi?A&_I<&fe_X;h7@3{UJCQ<}W_IKMxh}hRuj-7QR#1 zevI0a(b;$sZ{m(ceCX;bGB6an$9nTu*HBMvw0Uf_iBw)!v9p~n%fyuXO_7)Ta(+s7 zql}XixP02$9e}VO8U#&H1iuF4bY5Kvh)i2So^cZ`$!e~XW_rmwrC_a+dUcEg8Q*M+ z0BPooi?4itEaGZ-(c^e!<`oP%^w*oyKm7h1lDI^&2hRA4{DM*jJGRrtDJ>VI=4gkg zRYD4I2N~e^s{}=wX$y=Z`ltX!B}PBfR`BqXYoZia>7N`Z;asoYay;)`fZ~X;AO6U1)psZfNN0h;WICT!m z<@A{rP^e`<0+((})0v+GFp;zz?*?Jlx|X|gU?Ud{C!J!V;(gE0^u_v$v15F z4g~^jhjzoK1ad5{x8ohJ=Xh#X1;4_`mYS_Nxdwi=FHi}Wt&2Rhwk-suV%`Qy3Mav8 zT96{|h64{iKcN)2Q>;j59qdvZ2`B=M#Xh$s1-ar(+i>7-gv^(*zE0P(A{D`p!W$$1 zMU_l9$Rd=MWXJa9rpB2YUjlcD6Wj59pt^cB-MYkqm}lfrm=8BYB?n^28*DCiXoB$_U4e#6h*X&Nox!N9E=P|fS7ih zc5!mY=1+nWfii^C@0n2L3>$)5?%2cHY>qv~d_?{@T;I(;fzmcz7Y=ZUp8#UrIl_Xa z*$iT9S^*u%|HYF)SVaUO2=L;_xz_f`j)eYZZ6!B13)n{}wXCip^$=vERDpXpeSckK zUNmuMnJ@?0+FiG2G4E{p+vP|Pd9gFDfyC*zTSIH2pQokVJr`Z_OZnC}2Bx(=3W;K$ z9ob6+<~DQX;5>$)NS(G%TiAy{NA0Mr4IWUQ> zznZ?w#+GnxYtvr5Mu}(_9%t24)sP_HWfpoNM#t;;Y&qZJ^p>u&YHM*kw}EiQNQ0iX z(wOX6(|TaMnX}c^Ep_`Z&$%L(r)}@T1!M8M zSKT+)I=Q}UJButRWJg|P#>!VF%1`%}m5#W8vwotdv~CGi<{_O}tD93z33XzVXK$(t zr{CE7p&tMI&%)b&gda=6^UA6T7$1DJ=ZBt+w1W&yYmrCMHrea_)|`9?wejhes% zB^G>KQn(UIlbvm&2x6WN1Fjjg;J#^(Ef;#gwAQobG?ien@Ne@#=NPtGC4xBLfbZ@H z^jtL_1;!|mbp!C~99!{dH2?5v?<{!Yzd-501l+g8;||_ya(lGl1U~K{z0V9296_mn za|HSATmZF^Kop#dN@*rHYADJ>j9hRc=1d;z){)Z|IKDQopN^az=sl}ssL3i3S^DJx zkgq~{vV$Qed6m5P3?w>upOCv9qU|8#p0Q(V^R^7MR?x@_Jl1ftrPd-Bs@%4pI!&KF z);0`K8EVG@1+~xK&?j$r-;YwbHegJmOSgEU-$} zP@*9V#GA+I%5H%}4`po&ElM|*P|Rx1bsA5_>LXjFNmKmbk~D+8vZXChP!-T=@Xmg` z6>td{;f|Tk8=lZ5iDS`r&DZ^XdzowOW5X=yv%l4js(wTshTZ!PdVxE=rEr5yZGMj^4r+S!NG59u)lkNVwAUdKi}k8TTp(U&YP=WiT#vpzE0Ah^hiG zFrf0h@PLxdX)0HFr44wjZx9yeKfF%dpDKnd3*sB2@G-O}x%^|yEC`|wP zhLr!MM7+aL->Fjk_d84|{?!oYnJ zh1}E}vK?k>d&~K&NZP|k!(*hDZ_Wjkeu0)1dM*%fgG>v-1oZ`~2O21(9%h@hr5US* zrv7_{3K?AJ2p-fNT4W2(q2Awxx&|PP8m>bv?E^7FAYBUx738R@J8F({zuj0fi>iiU z!1aXHnKCMa#<&~Yrp@mkf*I8S$|$7Mb*4eEatCivCGrYNzd9BlO3d7*bTAO=m}0c@ zEwk%WGqM7&mdRQI4CB`S@|@mp5~zRcFNdYSfD0Y_?WkGe)hXass#R=E1gm3xgjrGR z&_h5nuk5z9o9ZM548f*`gQf@k{Q7`TG63^Yk9|!}FQG*Ty&udgh+U!)R<(_5B!QJ^ zJ7qY=GU#{*SjyUC2q2%*fbih%{~5sq6guV=0=8k1KXs@`s`77I224lD-wEv4X;Is* z$S6KGs*Nroh6M_HntcFCPcO?6B}>D0z7$$xaYiLwi_ka#&NN1^arIt@mAtX22& zOSZK0_S@x4^yo87L{-h(faCO4C-#0+=r(m*PaPm)=K||Lm+3g&P5O~Qk84)*wr=$( zo~{4^DyRI<``OrSdH{X|`$sp@d{QGwW z@ZrDjrYBlXgO!=y)nVZHc;Q(^jR14jy@VtnWEgxFm_YakaY0fI9`Tym_ttL94*$YGF2S8VT+RIE{wL2!scF7INYUzT#Pmc50d|%?tUMxG z1veI&44`?D`{B%Y!~xPfkHpLlyp<1J^C$ns2lKko)idHNg(3o)XPY2j#;O#w7=d$i6|oOCk;lldN~=;+A?o@C6aia9!s}BK zHW;mocRoH6oc(fyj@Z0?d)X3LusO3lJID|^Y)b?gI2O4h2i{0m+&C9OO=ppP+aO~5 z^+Mf8NL-Q=0Wf9Bx-DvH1V+zy+I9F+1Nep&qe$X2bet8}Pd?gx@M{g~9zs1T$jXup zA~?`BjL`X}b*B(m75|+UPlaPg;W4%_i{6oxeB2R`M~6c_pL3Z>Nv1a($=2s8v+rtM zyqE3s+6_;6nk=MXBp+*%A2o%yK+ymkF6A)^@`k%SzrU*$V!k5Nb{+^c{d>RfhhHVI zK;$Njtk&4vB(H?JsRS0;M^VcSa9>pW9q;vhc`>^&?IFGsp+e@4}!d6|#4=$&N_!$V_LKPocUA+dNt zZ^Mv16hE(^Tt176V&un0Z72=!6Z#6bm0r($)+s2-e4+9dLHkv^H!$0(M+};0n7#nF zObfe&rRymFkx|`qf9aZ))0G4+@XGvc21^GgOS{MY(f4EZKBZt3MpXNOsP%ruS#X{c zB38#C3v1YnrpOIj3AvOBNJ+`UM)SW%Yg%uA>@r17b*MEJA=rK-$AKo%R@j5Aeuz?b z1=oxBmB)J}q2iWpd3s;=?~!Dv@(6z^GVnv-C`MjpQs#yLn%v%~;O8IsZ(;kf0zQY< z#`nzkQD%2vfY8n@zkP^hm0vNtIFnb`cz<(PR zwG6gq&1~b0uN&ZPo&?K=4`R$Uv6jW^!z-EFa9_PZMLA(1!GB-Mdt-&dUmW{o0VzB7 z0Ws}`%*4n(Tm;@w2W#ZlM-ftpfi@kX+^|H^|&gSr3BYTV*3$Q4Wdu0 zkhBD7dOJbkDp}b$>DD&M=`Rb%V=%u#mebRO_2qpI=5)K{4A2hh=I0?fDo(F4PokX! zM}rUbCwWYPfO4=5b^M_wM{}?q3LOt4T-nD!4UDd=g{1a=S|FJbKYW?>F;?{g46*sX|g)qSXE1CD!b(^-`=%#8Wd zqpDwPP-jiv^C; zk?E7r<74??XZcpcEm6I5VW)`n@Y!MUEg|RSDF)fk zU=P%X8W))?P~5RCZ%4k4U=XjnOQs6OE95=angnM)?lvR1LdbAx2R>&HqhpJTnm0I; zTc!xF`47AuicFT@zpVH^Xli4U8>RPg>yJ9<%JaVCK~muuIT z9lzR+3+rFYj=FG4+{0~(<^iWDqw{%9`4B$>P)!NTGrf8X#hDk+E=}thxqzSW?ae8I zz}e+dC8H>ZBWKwo+J4=wK4Nr@w)ldfhO8Wh0EY3fpdPSS_QPkd5HER4WcEwZRJ{b1 zH`>?8H~$b6K?CU6_JX);{6e`HGsAUbK7SJSzcuXeA=7NA<%dj*mF*pnD>A8wmX9g- zKw&Q*0pLc%_Z^o3$I%w%TSbvTH+}MsE8v5m?hs40vXJv&9nC7TvjE6|4X$ zm1b}OkYTf`Bj&>-eBySXVG5Ot%^d>h7p2dMShZ;#le!iDUDqS=Fq`U(i`o{{?m56ww2=j<7JfUUhgYa^Ql>Sj#uiB^0Ce&J6EM}~b`WZ5IIhEv4m#D0}Q1mE& z3VK!*4hAcFyZS4nISf{^Wrp!WV~P&~hjIuYl$qh1Ui0e(3Xw|`naXg`lx{)EHFBSB zUjT<0aI#u{LvIO?Uy-3NH7gampO6C#&m*p51FUr=>eQishvRr^goMqQj&<6`p_;#n zV8EFbG~k2}ngYr`z*Ph&8`W^^EP&izz2Yhnj08VCeTj;yDv~{q0cUm(AW2C#Kk^R# z40bW(e;z#+zv(f2sprM!29awe`x*ic*46Sm7F=CpwTOSI8|RAZclo|6iw?E%tf zNNU?uF*|*$;#KSTecM#=PeA%>d>!GI$Q7;!k|vTW^MFD$cq_;M!YnPHgxtQFCa3m6 zm1~irw4FgTRFJ_bX#5@;hJe;>pCy>(UR{iI4gr)$GA3v?>X5GAc#f4d(2gq9ckDq{ zjcu&qMem3lUQLXa8**1OfndrxY(l=#=-WBwon_L9no!H7gny3I^3Uog-h{R5UIj%+= zs$kJu;u{Mqb&e%Rpt9p!93?}nJM9O$5J^~sRO4`X21w+V2Bc>IGfKEEJM;GBjsqM_ z+#dQuVR##H$U2R?Rh4<)>%1szm;hhgzo|#}y0^&fMl8uOn_wxtrY7(E?fS0%VVP{n zLZd83?ALAhoL+AM#wm`)Q{-j1lX!o}maE>u+BL)v?%6!BUm>v>HR)GC2JQzK^1cf? zc~=lf0|df*{|`RksU<9`52Wr(?r;=Qi8S2K?>LeRV5b6+7O4H7lK)#YcfocQD`)$# z3gLQanF-&Gg+~3#kC4H-tYCmaRn6V9XM9pSuWjh7eWqLQ;cU#Nbdg~#9*?>JyJ zGS9owXV;FZT`*&D!e})Dz|I2=zaMNiUgJk*Z`+tm zPPe8)GJ6{#w1&pJR{gd=ZA+Qc1yXM$2JG z0=v+L;ltqY?G%2t6_Wb;b$nC7DT!xjoCe+a0{M>>_(|n1Mr;K6c9C@ttUvc-h^deX z5UC;!#jgyy(IG}v6%~%rG}52(IvqVKTd)r&O$PbQzK;WiHueL`k7}AkC0&GLw-C%L zd29?5bS3~x0LOBl^(tv8w9Ww_BzHV+|7Z#dYZ8n9M9Megq4h&yk;Onzw51FT6(zo=G2IP;%S zXP)Y~nEH47FkmLx@>mSohp+Q_odFW<&{5I(EUPnqT*V8DiBvnxmesB8fMI;==N-E1 zkLg=?O!jvHd`W!>vqMmPoll7ZA5=I508%RlgsTOpLYI0xwjKiBmv!1Hg9~B^?{CNI z1E1-`*Q$O797n|?(BiWWvv(3HI~~CHA~;{mL!y!)U_OMs*AJ=E2e>dX&f)%ga^E6ENiQ`qB?U(PL9>d_8 zAFFty2%Si+UTH~pKZ-n5$mT0qxP60i*v3iJ`d?1TXBcGr<9>Ixa|)P4E7~6yrj8&T&DMx`bcL_egvH{{7Yf zM~R>t(h~l{R&TFIK6&yJOr^TQ5qk~NN@w(T8PLq9fo1eR^ zbZ$p*`j2P2{nNzB|M-9Yopzz^T=Tynd;Mz!(P%jEA5ucN4Ww>HiU^6L;V_5@KG5X> z&=HUv1GGbHP1y48xKd=f0xaiOk;a>xnycyF3BhWyI~zGv_t0n`0+p@mlLky4h=t-~ zHmqm;ECdFf%$-V>5)hjW$}xZs=zxgu3E?r~oQZcs^#U4yCywUUAxQ#_6+z9DFtp_~ zQ!MokwL`01ut9(z*bnlaHz*&%XzazF?hmNm_B2Y>%z23@cQH7g>nqS*Knt(ws*8xO zKRr1=c5O~V!-;hfP?N)ZR?K1!~ELA_~>eWA3sfM~t0;h??`@%pM=i$e)q(N9ff6;c5b0IX1w0l}+-N(H| zDHVWF1e%MGT_3gxX{i!UssR#Kphv8^9Xj=vQJd8j0^CO9pY=aSYzPr)3Lr&Z6#+=q z0Bt2tr-)$e85o4>Bln{leB&4lws{V86<^*?CklvSnkZd(y3QknUXlx|T>&Ga#w>b3 zr6>vq6FF*4-Zqv1-Q`}J4%B1@Fx^ALD0xSovvU6n2LwO!UYaBf4=?KYn#~D2O|LEw z@O(DP-x6E3O6xhZZaLtnUK&KyD(jKotXsquPM>kD>~lHOGtIYz95$OqQHReIR6O}f z&lT)9cQ$%7#1<5MgD+z2v#rE=_Wt~S%W4_?E-Q?=nKm*D(|XHUB02JvH`bOS=wWe+ z<9|BRQU3fe*lU0`l{7T$GNa{*H}GQIDCfhJ#EIdoObX(c&o20?NCQ*kw6)2dlbKm3 z#!%_?!Uq}X`=M3}+1fnlWT_+V^?V6zB*W?WjUVbT($zmemo+rwj5WEe%y6ygYMeMi zT!!Wm^yX)mC+Xgfv*eiw-2L3>BzN)AQ+KJjtEsA~nvxQH<1$!a82ReJ_#p_!3S`39 z8Q4tJ=g?3W#Da-s*bt}i=I^{U3I!90kO9K?2v^C9KI3La1@QZa(KsJc>9CthkXs_`W0wmqBW>_gBHNUnr{kGUI~d4YEsp88Wj0?;JJry zxiA(6T?mPR`^Xp$GGgsN?HpayPm>FCm7tSm%%!=uR5eQ;gilifC3H7)apisgUAR&N zCVQB9CYS?|joFD93^<2d*ryux;g(gv+88v+33#Je13lZnAa-W{^&2&9YsvL7wbE*$ z2+-xoflLGLn2;t?NgQnlei$)mqiOR#wht)^&>}=@ieM6A?p9ZUoTq_ftcDyn$&~m; z1^;pr~U5Vrkc%J9RG-5&o(_Uz@INyV~(|6@-7&+lxUu$>F|I7w>auHAdlJf~Q&6E*+{ z`v&z95_Q#$38*qdgK*SgPy=!*lKMGR)O1wlw&OAT1}jM3$+0KapgS#AC0X@A*DzQc zRl=<+PT03@jYx~X)LZYPScb|362azeyFhhFf))Y*;DhQ{_ zU(`zG0#Kz&8mff&3z%8Z2P1M{KwlEi^gPt+7u3pdlOUZ{^=g<#UCjr;Qw}qd`_XhB zn3u%K37G_`)Cab0G|{8RCveL93&&(x1&|X1eg_1mO(!DICLv|{v@GXkONd?5bxM02 zk+BsyCy~#)4{pyF*p*_1ZQLH}b6;yT_ks!V$vv7Ef!gX=H2Jj-;ZAXJG`A%iNTvR{ zIW+AQ#PX~^)7}%y12cdIhX!F?wF;-a1-ijv9DfaTwxL9Kl2v7-5hII+5~HzNdv`9| z#3Z*&ma`UyD2Ga5k#dU$YIQ6gId`kJ21rP*4;CFu&|KGsB)(TXFM8I&vy+2dDX1aY zK6i1X;S4C#5p1K4o%V~P;1<%2fApcmJq~2C8==0OqC-Kym&1eQ6ZZh1r$5%52!a_9 z2JXKmaxJPX|2OD54yzYeW#I06HM~KrY_6_`rfGVfv%)@%5mCN$7f#;aBwiZGw`br! z-60?RI;vD``G8;$Bb6w1YQlev^@t0JS@MNH9SN*6^V`L~z;pWObxgw{IvEVXbqaWL zk!8*OpVPpO?v#t%|4#V;^SEZ7<(f2|<$`9T);}@((H4_N?o1$vN&S-0Ao&t@B^R1^ z<1|$Zm?3i5Sr!bng8|Odny5_^_-ku;6cxZ(c1H74-d5VBrlK;~LYilB{{6ep9PHZ% zru+(M1n=#LB&HT=QzF^DfEg9eJ&gZvi&I+2Uz8 zE@ZHw&qK1^fg%mmnE@;dpEwiv2qGqts#Jsas(fF2{SJWR!13G3Dz$?YiKf?j^LL!5 zVrhq{Bbj??&|hh84h;rahi)++)EbRk-!SIDJskQ;oCpB7wDU+X4wMaPNqd>7&=@f3 z@lb8#okzxKZQwoTQ;2BFT@2Uj8%DNU5>sy0a1zuhCAREFck@0h{i zD64)E8V)}KtdEX4w2L^E+p>#^ac+QR4ej8?tY0`RWNSameN> z94^T<4|wNyt;1jD`ZbxSuQ76NZkY4Rfil&8zi@LS^gPS_%e8J@%WgVt!?xS3CG6z8?;5s`0(|k~5$|nc5x%$_ zY`l#Q(T4wgEp|I)!54?l(r(j~@WrDG4LcYLzIyUvN4SD7PTu6*Zrg`1{++jq`wen! z2+Umy1v5%$U-_%B`?$~$m@mnENe_B`Zfa|XyU~k0yfConB*HikXEzwoM7KY?Mq?U? zRs};q*Ia}F8$ZoAq4)UO*PtTMSPbo<9m9Y_FpKf%yA;0*x-6xbw53H@*x9~){rV2{ zj1R4K`!UPj1mlz3RA;`Nt7}nvsYj`W$N@>vb812D9$wQ0)vgx!S-C)Vjg=`1iWTwj zV+NH5d3#^reBy=9cUW*-Bj4U3iO2h>aw#pJ9-!fe9L^2a(jXy+iD0mTTHSoSm(u)N zD4k@iC^V@K0jI+U;ZeRpSirK=n68tWLBO>6d|@4+q7X>n!7%LMV{MoK9%b&UQHRhi zg>OHHlTtoR;+D|HcJEAe$@-jZQ-*=GQi?kFTX7HfrnnnNvhIBPfpB4H2qYOkux)Zf z7uC&KXXtY>iy~y37yuiHZLif|VlBguPVEXV&^;6$!GBYH=GfWI6j<=R|uJ z4x|8!P<{*3rfbhk=ZA1Zpgi(JTS_j&76(Sg|NPyktow2u%dJkh5JX2^9y>(tcDU@7 zqMq?tEV*G41nLX$^1Q2agFJ&ZK>{!~)Q}1dRZ@dgQNPzrL^q=Bqssy2KgeJzH^x zeqn=dF~WCCg{yyy>ogQ|8dh&3@yy=?i~xF7y_$%R+dP$NN(P_p(e7C&TtlMw3tK zqvO`6znQkBS%4a60gc2LiJEAiLYMJ`i_GeX!o3bacc!s@pEH~nO$o-x-5GZJHeSY1 z$f{c;Y;FeN9d?wH=UrZ&U>mP5kRr0YIzIG5+6hDuQ7jfZz{y4(u)VCsWVxJMG3M$X zqIR+>2c77kY=2?m6)8&nUznJz==%IyFTm-05pVylg|sa|AvB#E!qGh_ewm`ASq4BQ zWC$1LqE`ySDGsbE#$Xe*0c~VD7%(xFfNdM6kjav1oae>GY08X`SJvF*@x*-JT5vAj814ZjYH z5D&JV`%uXY0VO;H0$(=erM_#*EJu4`TWT{wSjlOc=qha6)N9%sdtP|7Ju4wZ)FoHQ zeLW9`ZpGn;@jGz`QrW~X#;0Oy`!_t;#&vfK+t+yaJ% z-d~#Tv4SZap(COjTfk%Ga^p{k-yAQ1*-N#s>N-IQPT55^gVlz?)3@HZz@*YgPSE*b z5gU7Yjr#5iK+G^^*}!jm>+dYr%gn<8F>xu~0B-w>c`?PKc~8Bw#@F6de#kQTeJJ`p zHs?Y-IRS7hr)u)ijkaQ~^mt%L5l+TeL_oM~Lw1bzz1RWc3H~krw|n+eUjXHo4;~9I z*d8(M(Csd#flAW7?0aLGArYsQ;_&}8_tsHS?_d8Yq3F>AiV~741|=#;m#Ba+ z(hMT4BGTPM+JFoS4AM1pcQatpf^-a_(lfv)jR@TR@to(o?(?j5pLKuh{&W4~{Nq7p zKJngrziNvHABnt?{?8YQ4UH5R$)J3jP>I6BXg$EBWbR8BOkCjE2C*y7lm9xD}W=^Rp#i-z-yg2;KY#w$exvE%R-`2I++iP?+p^s2;B-*7Xf>dxKEsR2 zwJZ&WBFmEwaCFwuYN-Mg~rrbW-wJ-k5-p# zfrf)n^cgw;@%Ipw)`t)+>1#{y9Q+0^MIj~Xl9{|xGBwp}`7i&~b)EVk?esOUHTi0z z^+zoGM-Dt^2gz3{-@mw{5ubNlT26^bpGPSPCH_ykX0Iy)SvemdMq`h$o<}0 zQHQ5@k&GCf{0iWB6c?I?2kM6D9yAR}_;MUo;OhVF+rQ!Izg}U{&ayq4t$oJvN&FLsE!2DU2H!0;_>{C^GAuc35BtzK8)F%y z7wyJB8%qYkp$N!F#ep|T<4Q)ZV&p<;>4Vn$4vjk=NRb>;u0pzF;Dv?<%`o%luE1M- z!k33i;eznLr!m!0^AJoesPa3YmsuFPhrH@Y^9RvrH3k(nQ3egZHTF!mI^o2!Aq^He zY9z^8pDFKCN$1Olhb$f(0CA8;+rCQb7yM5C+yY>cUZjMh=?ajD#FlGv;Ns&U27&%t zUq(Ik`m+d=u=P521-}Z1u@Pg4v=je41?bLaK(x3jx~QpwJ zoTlQvjR65fubk&9Vs>br5_ah{s- z4u$O-^Ji_LCrvvDau4-7N6?qB#Pf($^j&7p*Jhx4?H~TfBCYT|9n}PV+YqXB4}^9e z3GrI|_wUa4WL(SQ*GdV@0a`O+P>e3LM~mM^fxiJ)2|h@(5XIw(yuUddaRZ=oyCe#H zsW@n>>bT;CPGDOrq4;o2-_AfWQ^+ucl#=;x=f_kz^G3jpfuYC(spJl@`f58stUO2C z1;Vc?ujy((Zbe27SpE_;KU!19Z%~@Pu?7=HJRlFljgGKFg3tdDm4e|v-D6NH6ys0O ze|!*cL+7IT(@`7}(CQNm>b*(|P6+Dd;%Y$1qz?UQWa1@x`SGwzE;Ai$uE5_B(P*|{ zfohxv8TjT>^I^%pNVCZikmvTn^M84G8ag70;hmg~*{)>DPNTq-=z2T2{X3xjsV~yc zyZyOg94KNmZ2eMb!YiK;!|>auvcG4tp4o&K8s?)&|I0N^moi@d22isDTF?ik@VLj* zXmee4>(o8Kq-3dNPM8m7XH3L}*@QA-O*}#9KGImx1x@f`A{b`Z*4YcJy74m+w=Vw7 z{K~XA2x{JQhP%+1Se{plxeJa72Qb;(Gn4WARlXz7^ym&=@h_S4qoAo<5KDmwkS1gx z5{4jwz&okk^eU;~vm>G|>ZNB}#?T3N#);Xgy-9mHjkHVNg8GGaHUs%=>#HNrLDEpu zS#JdSc8;k}&FgzmCIOu)2C0vZA-Xyoj#FOVjq2?KSwQNucKP`iFdyt z_`qYVmj5>HnZL|#I7`Tv&56BTRwuUFZ*E4KXXW+Na~^#KGi_;eEM_7%!l>B*WfhQp z-*|fL+lLp6^h*$YXqOx*coSZCTN(c+n1kf)ztCGLlxYw}2*YDCeqR5ZRfPP8l;B8JSWrI;NJAETkKIAz20(xN!@^{ zuF#$0z!f>Fw>s=9CYAwESTo_+%LEa4Ca|{a;|jCKm8|o+m1lRR=KOUwc56E!HtIlq zk)REtQC$?jsl%gW4(jUCw1X-@ZEnHeSvjU5ltaUsbTkuL|>;Cf4! zK!QNAB~7J;N!q;bt@r>(<-EEJiRK8=h6@<&Y~&#Nyp@o6cf9q~B{ z1#&sxpzM5Zd+@7Q8%Q)$5`4IGakF4{ShWM&T>d=b|55DSlxG*SnNk%58TAjOZ5l}e z83o3JGR_q>-H|9G@zvjn8%avRd#^8zk!#?bk5tpoRAcJ`QX<0cU7d| z!%gT0>EjMa1*1ZF77Rj#jR&}*vow=oo(9$N3N(vnTVD58OU*9$2{{m*tV4;E9CmGksb|q~LMmXt3|)_)2^l7Zt}?haXJ;|9F-cHu?vTGo z$-x+z1XUPghSbNbyYC(+T`(vevXyIw&m{+Pk#aH;?RAH&v^viadvkSzT1M*mRnde& zal4_f7)>X5vqoH>?;hM0~LiOYAutu`PIpd z3x?%C2tNtnMwMJElQll6oy7d+YQS#LrJLQy5Ho13jA!AZb0+s- zh=Q)8{bzuyq;;W)qBSYiFx*6jx_*y8EdQqO@Xj+<(_*T=U7Q?2Gc2T4BLV8r_j*nz#~^_|6J zm+NxK4v5zexDX)v(8jSI9T3FYVI-9_=N#Ae_1~Q&?az7F=GPms507&SadYP(hA{Ep zhc3h7%*CiTij#X*cU{deMG$?rE~&qj>K(Ja1_^E68pOT z@k2_7NsK`}BSAK_foeQ>^+1&?inU6~7(Ds4_7rXsI>#iKfQJSTKps`pG-4MYpUVMn zJuk))8pR}NN1urij?ZTvj9$5R{rcmq2dxnv@xE!F0HgVyV_1>v=LfW!uu&)E8QC3q z2d@?{#t&369&FDJF_#9&Fs1f1`1x!n;TeAWe6lrAnP9nSJh!+%*Yp*`nlD;3ibv&o zaEmdNdrRo2RiXD!d$q8dXp-KvJx&K>XFof)U`EvaQMi=XEg8 zUO9!yIWs#+f$>qp4AgmOJnlpcZf{T=qXR%0eGX%id9PZgAcOz9qVxq&q!0A|$igYFD2n5sH&P`=1*t;|-DVXAa_ zj&(Z>RZ@Q4wF{K6{q1uD1@R_LfSX0uXOS;O#qL^k!hyUX+ol+}!oih4-X@OkW-oMO8MeN#EX z^n?4>c6$Opka89{D$+Se@z-9am2j@f9#^`$c{9`MZ{9tta-2p$gZ64H=8@p_A~?T- zT~cKT17f$;^WUWX-XK*holMO9Nlb@JC5~!J%|4?`M$%!}|{6M;p`w*{0xRm(8t6NjYIaG6kE(U}Q-CnI~V%APKd6;f)(p?9It#tajjn$q8AOm3s zawzX6VA8$c9IDNP{969s;6jRpw2UurwiHWfsC@Z3o^bTD@{ynNOpP@i-Y|P!*#C-C z>i(I5-%{qSzZzKo;0T`S(fh8alpoF=)!DCZZ2bL$a?U%P$F-d2qCX1vw!dAtN&C}b zyna}mlzkmG?G#iBtFkttc2b&T%=i<>2Z0V)IQ0(oDBWHgQ&yhR=g|W)^s^MHD5Fl% zk~?8^vICx}ZJuT*t_-?*=yi#0Vi|d^l2OyU%qt8T)aXMfF&bmwK!e#AopyUYFCzY# zhz-$GH9f}!)F0T)Ka_&jc30fjI>oiyQ5)L;K~N>b1fMGP{W&;y2YN3^PrJ4P^z*>^jMGF;Xyzn%5+=hz^WzX~iRH($R^I^)@@ z+;~@W*RxPfYwf{&19RB>W7*q~>ufxaa^LOVGNre5z;+<@Q(W9qJl7bF5#nmM*<|n_ zuynxTVE>_dJ7hnSJ%qhhGf>Ja2j^-Z4$5VB zN}ygyLJWgqFIiq;u$Z)(;kJsm)lHn#n@I5)gNHE|p8sLjq$M^tp?Danh~Aef5Kt;L z4f@<`pYjDNM(5o1I+i9HuUdV$jfzfl9#>?x0^F{AtH1xrXYP7u=NZT9F@AuB$gE-Va9HzAt4DgkNUdn>BadI%t}(5t^&I5y>W&R+hf?T&ykXPbp+L*r1)4tEO+EC^>mqdByd#>lZ1tS#PXT?$5v0oTQ)5x$mt6 z3lK$@QUoTM!V`!2T=XW3p+0;;b{XBxiqXnm=#xk9E9Sr^g3*qH`0d*Ci!gWhke;=t zJeJUVEg5#wP>Jwbpq%PV2MHOS2D=+&2-Zn>Gbo0HWlj2-nAg~F-k%`Tn6<6rJ25#X zj%bVbwvnP~A6=*dv*89Dd4texc{7|lcc0EL=`|em5fu9m;cuqnZ7z;5eVeq4MYjv$Jh_$b z@fqeq|FG_;)RcYw&V2vsHky6pj&EUKk9bb_sCqRqT{Lcl6%3!ZB0}`H4Y`=nvDz?x za;RqSWF0JrnimV#t5=zs>?J=T&nj{tBVxeuPI!+^_8R5=W7Q6j zdHb60dq!P<_gNJl)QgI=`B4k^u-NG`a~LB<&X_NVL*A;k>Tw(C1k+mzj; zkOyI>ksC4T;H{w<|JE9D?j@V4S3rfqEueEY_3cYKIW1tv*-xewXr zX1$K8&2^pHFcGZEvy0nV4VnQJxxH7^@T)Dddx2Qh1za6hT_fTgT3=4`|7Bg*1qi^` zU%N2nFKh!1>E>rPNcZa^kg443m8UR07~}1ZWtA2B7PTW^eWM4ORUTpjljpW}kE@gE zTP_??Bov&RSJ+1tp@oj1P<`BG%1Gx6n!{h5~Zrap-c8k_q#34Z4h z>urbj6L&UZ5&!aHDPc;<{QW1LV!!mc*KmWqvVvz^`Z!E`AqbyVJnnNc53)IzIsU!_ zgkwB}!TKSjGl&z?@j{73;SKu^uY*pkEV`_7=zjMv<8M9U z))x-(hDeOs_rz$71dyonnPgEl999HmA+O@3JpZvZusz=@E$aORr>1s!RHr$6-KVSf zb@)>e=25rLWT55IGy@~z__n+P@BT~oV`@(*xy~u`4?plg7BIWh*`|bAKaX~7;d2q}UYh6)4Z~s; zp_`N9IT89%vo@hCv*{XWB`urGBg#=IjdSi7q_$P~FYZ`3=9IR@o{wu+y;zan;~paL zW2ey*JB=UgyUcoM)+czaL79Z`G4e9Z0}Tndd%1rfc_v^Q^~yMb-PD|_vjCAx})z}r7UCxLa(W1z1U*AXzCcoA@bHe;ZNjB1`% zHlMS~SHdQ;@wrzF_&W9~%8r6Pr087qw_DrIePsU5X9gskTwz(wWTu?{mZJ{nf?N}aS(rK^`(Gl5!LsAw%MU7IdWmi(g z{IQAzXaKzLtIiL>{5u=`^5x2JKz4&Gb0EXfBYqrG9kMUZf}y*3J{ggp1-66aD%(UE zi1WyL1kKt`(g~14(A$lwMgS^_x^*7*GCMKC<`Fx_Dn7T~Tqv0sRAM!m+5)fu@R+Ey zuoCFcc`=y|iKWnn4QJN-s~$n}Vtk&s%M?W!W{)edcL zZYoZyqqLp{s%C(3UX*verh9I0S&_35i9I7f&5en99kqPH30JGDki7PpVX8Vc%WhGH+S zWNhH%Z*BLfM#aWWOX42hYPJF^1&u@2`Y^Oq_K-1jJpO$tnDz{m{gX~A;b%)+S?THte9aMYkp5gbtp zKi<%7Bs~*#UXK+66_Z3jfLp$K^^9#Cl){gJ8- zw11fTUiR`NG+UbGp%AV!%*UcF8j7H3D&99-)MlV+ajLra0!xPX{Z#Q zN04Tu(}RvPPp%`8@k2h5Dpf;3?%j-_XfmFHx~MKvaNPU*$?i8j(=E_@5D0^QCxNze z#q$N@G#Y`F(}btnBp@1T5gCQ8uQ4jXZS;(=7ci}_wuGiiHM2-JE6gtd_AV8rA)Zy?e2SG4x>ZLB~lH0yFOh=2P16{(8SzUQYWXR(_7_;&4B0- z+!sn`G#(c10c4Xf=g#%2Rq6hwGQJhT`VbUT!~`z9{e$>RN^bL2OIHhc1|W_z?tu(k z>H8M&+>IZ+H=Am8xr)!2*HAP3YC~J}rIT(~S%HaYEoC}41eoO6-rKq8)-u4D&h`pk zzkF`O0tJmFgOY3`R3hq=fIE5P=k@dN+%q#HVBFsx9D)bi8v?l;i%z?l9*M%&RxBvY z-Z)i;B8N4{PKVEMypH8gxga?afVU=4$Ier?Jz3e|jT_*2ZNMFbF}lUF6FER1z?Mjt zso!O>XoD5}33;2ulDncO>M*rrccpQw{1<(>2z;}Cl1LklY;aovvUqr$6mnPh<8`>~ zk!o2<^KhaH1Lp3|70=r@Eyz=dmxezYm96YXzDS{$6{B9tM?n1>s z61%`3S|uzT=-f|7kvvm_qcXSyC8NXW@+`XPYYST3A8l^xvMAOSoU_fHx!%%u%XHFS z1wdV6pN5xBU$kF&B8B_UpY*F!S6-IF0TTlnydj*9m`$I`vOkdJ3xOn*aJBc!L){ve zX)8x0Q1G?*oB*fH>Rp8Q4vb0b7HSh6kF?@Uyg)6$2Hl`J$C#+S3)VryD(x!vK$>u> z0C0j+a)d&6LDEGnQ4`>@36nmM%pu;o9XG+|ilW%o-tD!LbNH~|=7Nmng#?A(IY0H; z(3?}wyFPAwbbK`#Eb_QCVdePjsEWzW-&>YF)?p|2Hb(d^E+w=^3C>qQ@S=g5@9)Nm zYhj$0>S3I!Mc8AiRulyZin7r1~4z*-&2F+mWw% zUy((JU!C0ZBu;+sFo-S@5^H>O#?p1_@~q30inRLm$H6k*%M)GEg3&*#L(AgUR;?o! zSLXw=S|ghsA{$qhuIxH3LFYCjk)O|vw1Bkz^U zrDk2sr85F?zVowQD2j#Rr;t8M#`lqy4YK6KtE^R1Wi+ZK%0Db?)mRx_fZ|XP8ANtW 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 D;cA3- literal 0 HcmV?d00001 diff --git a/main.tex b/main.tex index ce49627..9ed5e1c 100644 --- a/main.tex +++ b/main.tex @@ -40,5 +40,8 @@ \includepdf[pages=-, addtotoc={1, section, 1, {Гаврилов Максим Юрьевич, Программирование микроконтроллеров RISC-V}, gavrilov_maxim}] {Maxim_Gavrilov/Maxim_Gavrilov_report.pdf} +\includepdf[pages=-, + addtotoc={1, section, 1, {Брулевич Никита Петрович, LaMaGraph: Разреженные матрицы на F#}, brulevich_nikita}] +{Nikita_Brulevich/Nikita_Brulevich_report.pdf} \end{document} \end{document} From ef518cf86407f7ca81a6d9ee8e0ee42d797acb77 Mon Sep 17 00:00:00 2001 From: Brulevich-Nikita Date: Fri, 12 Jun 2026 18:50:25 +0300 Subject: [PATCH 02/12] fix report --- Nikita_Brulevich/Nikita_Brulevich_report.tex | 3 --- 1 file changed, 3 deletions(-) diff --git a/Nikita_Brulevich/Nikita_Brulevich_report.tex b/Nikita_Brulevich/Nikita_Brulevich_report.tex index 972ac98..e2bc219 100644 --- a/Nikita_Brulevich/Nikita_Brulevich_report.tex +++ b/Nikita_Brulevich/Nikita_Brulevich_report.tex @@ -1,6 +1,3 @@ -% Данный файл распространяется под лицензией 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} From 8198e833b2b27e1c591cf934e810404ca62e388a Mon Sep 17 00:00:00 2001 From: Brulevich-Nikita Date: Sat, 13 Jun 2026 23:16:06 +0300 Subject: [PATCH 03/12] fix: report, main.tex --- Nikita_Brulevich/Nikita_Brulevich_report.tex | 126 +++++++++++------- Nikita_Brulevich/images/memory_comparison.png | Bin 48528 -> 0 bytes Nikita_Brulevich/images/time_comparison.png | Bin 47379 -> 0 bytes main.tex | 2 +- 4 files changed, 80 insertions(+), 48 deletions(-) delete mode 100644 Nikita_Brulevich/images/memory_comparison.png delete mode 100644 Nikita_Brulevich/images/time_comparison.png diff --git a/Nikita_Brulevich/Nikita_Brulevich_report.tex b/Nikita_Brulevich/Nikita_Brulevich_report.tex index e2bc219..8a042a8 100644 --- a/Nikita_Brulevich/Nikita_Brulevich_report.tex +++ b/Nikita_Brulevich/Nikita_Brulevich_report.tex @@ -9,8 +9,9 @@ \setotherlanguage{english} \usepackage{fontspec} -\setmainfont{FreeSerif} -\newfontfamily{\russianfonttt}[Scale=0.7]{DejaVuSansMono} +\setmainfont{CMU Serif} +\setsansfont{CMU Sans Serif} +\setmonofont{CMU Typewriter Text} \usepackage[tiny, compact]{titlesec} @@ -20,6 +21,7 @@ \posttitle{\par\end{bfseries}\end{center}} \preauthor{\begin{center}\normalsize} \postauthor{\par\end{center}\vspace{-1.8cm}} +\overfullrule=5pt \usepackage{hyperref} \usepackage{bookmark} @@ -35,33 +37,55 @@ \begin{document} +\sloppy + \maketitle \begin{flushright} Группа: \emph{2025.Б-73-мм} - + Кафедра: \emph{кафедра системного программирования} - + Научный руководитель: \emph{Григорьев Семён Вячеславович} - + Номер семестра практики: \emph{2} \end{flushright} -\section{Постановка задачи} +\section*{Введение} Работа выполняется в рамках проекта \textbf{LamaGraph} (Lambdas, Matrices and Graphs), нацеленного на разработку прототипа быстрого вычислителя для разреженной линейной алгебры, реализованного в функциональной парадигме программирования на языке F\#. -Одной из ключевых частей проекта является библиотека \textbf{QTreeFSharp} для работы с разреженными матрицами и векторами на языке F\#, реализованная на деревьях квадрантов (quadtree). +Одной из ключевых частей проекта является библиотека \textbf{QTreeFSharp} для работы с разреженными матрицами и векторами, реализованная на деревьях квадрантов (quadtree). Данная библиотека служит основой для реализации графовых алгоритмов (BFS, SSSP, поиск треугольников, построение MST) и требует расширения набором операций для работы с матрицами и векторами. -\textbf{Целью работы} является реализация и оптимизация следующих операций над разреженными матрицами и векторами: -\begin{itemize} - \item Редукция (свёртка) строк и столбцов матриц -- \texttt{reduceRows}, \texttt{reduceCols} - \item Срез (slice) векторов и матриц - \item Произведение Кронекера (kroneckerProduct) - \item Преобразование каждого ненулевого элемента матрицы (map) -\end{itemize} +В данном отчёте представлены результаты работы по реализации и оптимизации некоторых операций над разреженными матрицами и векторами в рамках учебной практики. + +\section{Постановка задачи} + +\textbf{Целью работы} является реализация и оптимизация операций над разреженными матрицами и векторами (редукция строк и столбцов, срез векторов и матриц, произведение Кронекера, преобразование каждого ненулевого элемента матрицы) для библиотеки QTreeFSharp. + +Для достижения цели были поставлены и решены следующие задачи: +\begin{enumerate} + \item Разработать и реализовать недостающие операции в соответствии с архитектурой библиотеки QTreeFSharp. + \item Написать модульные тесты для проверки корректности реализованных функций. + \item Провести замеры производительности по скорости и памяти, сравнить различные подходы к реализации \texttt{reduceCols} (прямой обход по столбцам vs транспонирование). + \item Проанализировать полученные результаты и оценить эффективность реализованных операций на структурах разного размера и плотности. +\end{enumerate} + +\section{Обзор} + +Основная идея библиотеки QTreeFSharp заключается в использовании деревьев квадрантов для представления разреженных матриц. + +В отличие от традиционных форматов (CSR, COO), деревья квадрантов позволяют эффективно выполнять рекурсивные операции за счёт логарифмической сложности доступа и возможности схлопывания одинаковых значений в один лист (UserValue(v)). Данная структура хорошо согласуется с функциональной парадигмой языка F\# и обеспечивает неизменяемость данных. -Данные операции необходимы для реализации графовых алгоритмов и оптимизации работы матричных алгоритмов в рамках прототипа вычислителя LamaGraph. +\subsection{Исследовательские вопросы} + +В ходе экспериментального исследования предполагается ответить на следующие вопросы: + +\begin{enumerate} + \item Как зависит производительность операций над разреженными матрицами от плотности и размера матрицы? + \item Какой способ реализации операции reduceCols (прямой обход по столбцам или транспонирование с последующей свёрткой по строкам) обеспечивает лучшую производительность? + \item Как масштабируются операции slice и kroneckerProduct при увеличении размера матрицы? +\end{enumerate} \section{Описание предлагаемого решения} @@ -74,15 +98,15 @@ \subsection{Структуры данных} \subsection{Реализованные операции} \begin{itemize} - \item \texttt{reduceRows}, \texttt{reduceCols} -- свёртка матрицы в вектор с использованием заданной бинарной операции по строкам и по столбцам соответственно - \item \texttt{slice} -- выделение подматрицы/подвектора по заданным границам - \item \texttt{kroneckerProduct} -- произведение Кронекера двух матриц - \item \texttt{map} -- применение функции к каждому ненулевому элементу матрицы + \item \texttt{reduceRows}, \texttt{reduceCols}~--- свёртка матрицы в вектор с использованием заданной бинарной операции по строкам и по столбцам соответственно + \item \texttt{slice}~--- выделение подматрицы/подвектора по заданным границам + \item \texttt{kroneckerProduct}~--- произведение Кронекера двух матриц + \item \texttt{map}~--- применение функции к каждому ненулевому элементу матрицы \end{itemize} Также была изменена сигнатура функции fromCoordinateList в Matrix.fs и Vector.fs, добавлена валидация аргументов. -Дополнительно проведено сравнение двух способов реализации \texttt{reduceCols}: +Проведено сравнение двух способов реализации \texttt{reduceCols}: \begin{enumerate} \item Прямой обход по столбцам (оригинальная реализация) \item Транспонирование матрицы с последующей свёрткой по строкам (альтернативный подход с учётом уже реализованной в проекте функции transpose). @@ -92,14 +116,14 @@ \subsection{Тестирование} Для каждой из новых реализованных функций написаны Unit-тесты: \begin{itemize} - \item \texttt{Vector.slice} -- 11 тестов - \item \texttt{Matrix.map} -- 6 тестов - \item \texttt{Matrix.slice} -- 22 теста - \item \texttt{Matrix.reduceRows} -- 7 тестов - \item \texttt{Matrix.reduceCols} -- 7 тестов - \item \texttt{Matrix.kroneckerProduct} -- 13 тестов + \item \texttt{Vector.slice}~--- 11 тестов + \item \texttt{Matrix.map}~--- 6 тестов + \item \texttt{Matrix.slice}~--- 22 теста + \item \texttt{Matrix.reduceRows}~--- 7 тестов + \item \texttt{Matrix.reduceCols}~--- 7 тестов + \item \texttt{Matrix.kroneckerProduct}~--- 13 тестов \end{itemize} -А также добавлены отсутствующие тесты на уже имевшиеся функции - 17 тестов. +А также добавлены отсутствующие тесты на уже имевшиеся функции --- 17 тестов. \section{Эксперименты} @@ -109,18 +133,21 @@ \subsection{Методология} Использовались синтетические матрицы следующих типов: \begin{itemize} - \item \textbf{Sparse} --- разреженные матрицы со случайными значениями (плотность 1\%, 5\%, 10\%) - \item \textbf{DenseUniform} --- плотные матрицы с единичными значениями (оптимальный случай) - \item \textbf{DenseRandom} --- плотные матрицы со случайными значениями (использовалось в экспериментах над reduceCols и reduceRows) + \item \textbf{Sparse}~--- разреженные матрицы со случайными значениями (плотность 1\%, 5\%, 10\%) + \item \textbf{DenseUniform}~--- плотные матрицы с единичными значениями (оптимальный случай) + \item \textbf{DenseRandom}~--- плотные матрицы со случайными значениями (использовалось в экспериментах над reduceCols и reduceRows) \end{itemize} \subsection{Результаты} \subsubsection{ReduceRows и ReduceCols} +Результаты замеров производительности операций редукции приведены в табл.~\ref{tab:reduce}. + \begin{table}[H] \centering \caption{Результаты Reduce бенчмарков} +\label{tab:reduce} \begin{tabular}{lccc} \toprule Метод & Размер & Время (Mean) & Аллокации \\ @@ -157,10 +184,14 @@ \subsubsection{ReduceRows и ReduceCols} \subsubsection{Сравнение reduceCols и reduceCols как transpose + reduceRows} +Сравнение производительности двух реализаций приведено в табл.~\ref{tab:reducecols}. + \begin{table}[H] \centering -\small \caption{Сравнение прямой реализации reduceCols и реализации через транспонирование} +\label{tab:reducecols} +\small +\resizebox{\textwidth}{!}{ \begin{tabular}{lcccccc} \toprule \multirow{2}{*}{Метод} & \multirow{2}{*}{Размер} & \multicolumn{2}{c}{Время (Mean)} & \multicolumn{2}{c}{Аллокации} & \multirow{2}{*}{Разница по времени} \\ @@ -175,18 +206,21 @@ \subsubsection{Сравнение reduceCols и reduceCols как transpose + re ReduceCols\_DenseLarge & 1024×1024 & 1.14 s & 0.89 s & 277 MB & 277 MB & \textbf{-22\%} \\ \bottomrule \end{tabular} +} \end{table} +На рис.~\ref{fig:reducecols_time} представлено сравнение времени выполнения, а на рис.~\ref{fig:reducecols_memory} — сравнение аллокаций памяти. + \begin{figure}[H] \centering -\includegraphics[width=0.85\textwidth]{images/time_comparison.png} +\includegraphics[width=0.85\textwidth]{images/time_comparison.pdf} \caption{Сравнение времени выполнения оригинального reduceCols и реализации через транспонирование} \label{fig:reducecols_time} \end{figure} \begin{figure}[H] \centering -\includegraphics[width=0.85\textwidth]{images/memory_comparison.png} +\includegraphics[width=0.85\textwidth]{images/memory_comparison.pdf} \caption{Сравнение аллокаций памяти оригинального reduceCols и реализации через транспонирование} \label{fig:reducecols_memory} \end{figure} @@ -252,27 +286,28 @@ \subsubsection{Произведение Кронекера} \subsection{Выводы из экспериментов} +Анализ полученных результатов позволяет ответить на исследовательские вопросы, сформулированные в разделе~3.2. + \begin{enumerate} - \item \textbf{Редукция матриц (reduceRows, reduceCols)}: разреженные матрицы демонстрируют преимущество над плотными во всех размерах. На малых матрицах (32×32) выигрыш составляет 3-4 раза (64-66 μs против 256-293 μs), на средних (256×256) -- 30-40 раз (1.7-1.9 ms против 56-78 ms), на больших (1024×1024) -- до 120 раз (9-10 ms против 856-1137 ms). Аллокации памяти также отличаются в 4, 15 и 60 раз соответственно. Результаты времени выполнения для плотных матриц с единичными и случайными значениями (DenseUniform и DenseRandom) близки, разница не превышает 25\%, разница объёма аллоцированной памяти - не более 2\%. + \item \textbf{Редукция матриц (reduceRows, reduceCols)}: разреженные матрицы демонстрируют преимущество над плотными во всех размерах. На малых матрицах (32×32) выигрыш составляет 3-4 раза (64-66 μs против 256-293 μs), на средних (256×256)~--- 30-40 раз (1.7-1.9 ms против 56-78 ms), на больших (1024×1024)~--- до 120 раз (9-10 ms против 856-1137 ms). Аллокации памяти также отличаются в 4, 15 и 60 раз соответственно. Результаты времени выполнения для плотных матриц с единичными и случайными значениями (DenseUniform и DenseRandom) близки, разница не превышает 25\%, разница объёма аллоцированной памяти~--- не более 2\%. \item \textbf{Сравнение реализаций reduceCols}: транспонирование эффективнее на плотных матрицах (ускорение растёт с размером: 1.5\%, 11\%, 22\%), но проигрывает на разреженных (замедление 18\%, 51\%, 97\%). Это объясняется лучшей кэш-локальностью при последовательном обходе строк после транспонирования. \item \textbf{Срез (slice)}: на всех размерах производительность для разреженных и плотных матриц/векторов остаётся сопоставимой (разница не превышает 10-15\%). - \item \textbf{Произведение Кронекера}: выигрыш разреженных матриц над плотными растёт с размером. Для матриц 8×8 разреженная быстрее в 25 раз (92 μs против 2.3 ms), для 16×16 -- в 95 раз (1.2 ms против 114 ms), для 32×32 -- в 200 раз (6.2 ms против 1.29 с). Аллокации памяти различаются ещё сильнее: 86 KB против 1.5 MB (8×8), 229 KB против 31 MB (16×16), 112 KB против 576 MB (32×32). Соотношение по памяти достигает 5000 раз на максимальном размере. + \item \textbf{Произведение Кронекера}: выигрыш разреженных матриц над плотными растёт с размером. Для матриц 8×8 разреженная быстрее в 25 раз (92 μs против 2.3 ms), для 16×16~--- в 95 раз (1.2 ms против 114 ms), для 32×32~--- в 200 раз (6.2 ms против 1.29 с). Аллокации памяти различаются ещё сильнее: 86 KB против 1.5 MB (8×8), 229 KB против 31 MB (16×16), 112 KB против 576 MB (32×32). Соотношение по памяти достигает 5000 раз на максимальном размере. \end{enumerate} -\section{Заключение} -В ходе выполнения работы получены следующие результаты: +\section*{Заключение} +В результате выполнения работы все поставленные задачи были решены. Реализованные операции \texttt{reduceRows}, \texttt{reduceCols}, \texttt{Vector.slice}, \texttt{Matrix.slice}, \texttt{kroneckerProduct} и \texttt{map} прошли модульное тестирование и интегрированы в библиотеку QTreeFSharp. -\begin{itemize} - \item Реализованы и оптимизированы операции \texttt{reduceRows}, \texttt{reduceCols}, \texttt{slice}, \texttt{kroneckerProduct}, \texttt{map} для разреженных матриц и векторов. - \item Проведено сравнение двух подходов к реализации \texttt{reduceCols}, показавшее преимущество транспонирования на плотных матрицах. - \item Выполнены бенчмарки для реализованных функций на плотных и разреженных векторах и матрицах разного размера. - \item Полученные результаты задокументированы и могут быть использованы для дальнейшей оптимизации графовых алгоритмов и работы с матрицами. -\end{itemize} +Экспериментальное исследование показало, что разреженные матрицы на больших размерах (1024×1024) работают в 100–120 раз быстрее плотных и потребляют в 60 раз меньше памяти. Выигрыш растёт с увеличением размера матрицы и уменьшением плотности. -\section{Источники} +Полученные результаты задокументированы и могут быть использованы для дальнейшей оптимизации графовых алгоритмов и работы с матрицами. + +Исходный код доступен в репозитории: \url{https://github.com/Brulevich-Nikita/QTreeFSharp1} + +\section*{Источники} \begin{thebibliography}{99} \bibitem{qtreefsharp} Исходный код проекта QTreeFSharp. URL: \url{https://github.com/Lamagraph/QTreeFSharp} @@ -281,7 +316,4 @@ \section{Источники} \bibitem{fsharpdocs} Документация по языку F\#. URL: \url{https://learn.microsoft.com/ru-ru/dotnet/fsharp/} \end{thebibliography} -\section{Репозиторий} -\url{https://github.com/Brulevich-Nikita/QTreeFSharp1} - \end{document} diff --git a/Nikita_Brulevich/images/memory_comparison.png b/Nikita_Brulevich/images/memory_comparison.png deleted file mode 100644 index 9310693368612ca3a083741dbe391a99bf848ec5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48528 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 X|GC^=#+X994TUqxr_)Xv-Tc1*6X|+_ diff --git a/Nikita_Brulevich/images/time_comparison.png b/Nikita_Brulevich/images/time_comparison.png deleted file mode 100644 index 0ae046af4619b635b7ac0c5f2ed0949da623066b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47379 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%0Db?)mRx_fZ|XP8ANtW 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 D;cA3- diff --git a/main.tex b/main.tex index 9ed5e1c..0dbdde6 100644 --- a/main.tex +++ b/main.tex @@ -41,7 +41,7 @@ addtotoc={1, section, 1, {Гаврилов Максим Юрьевич, Программирование микроконтроллеров RISC-V}, gavrilov_maxim}] {Maxim_Gavrilov/Maxim_Gavrilov_report.pdf} \includepdf[pages=-, - addtotoc={1, section, 1, {Брулевич Никита Петрович, LaMaGraph: Разреженные матрицы на F#}, brulevich_nikita}] + addtotoc={1, section, 1, {Брулевич Никита Петрович, LaMaGraph: Разреженные матрицы на F\#}, brulevich_nikita}] {Nikita_Brulevich/Nikita_Brulevich_report.pdf} \end{document} \end{document} From 4e1ce98e2ef7d9c17119b44b51b9bcea16abbe2a Mon Sep 17 00:00:00 2001 From: Brulevich-Nikita Date: Sat, 13 Jun 2026 23:39:14 +0300 Subject: [PATCH 04/12] fix: images --- Nikita_Brulevich/Nikita_Brulevich_report.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Nikita_Brulevich/Nikita_Brulevich_report.tex b/Nikita_Brulevich/Nikita_Brulevich_report.tex index 8a042a8..2e41eff 100644 --- a/Nikita_Brulevich/Nikita_Brulevich_report.tex +++ b/Nikita_Brulevich/Nikita_Brulevich_report.tex @@ -213,14 +213,14 @@ \subsubsection{Сравнение reduceCols и reduceCols как transpose + re \begin{figure}[H] \centering -\includegraphics[width=0.85\textwidth]{images/time_comparison.pdf} +\includegraphics[width=0.85\textwidth]{time_comparison.pdf} \caption{Сравнение времени выполнения оригинального reduceCols и реализации через транспонирование} \label{fig:reducecols_time} \end{figure} \begin{figure}[H] \centering -\includegraphics[width=0.85\textwidth]{images/memory_comparison.pdf} +\includegraphics[width=0.85\textwidth]{memory_comparison.pdf} \caption{Сравнение аллокаций памяти оригинального reduceCols и реализации через транспонирование} \label{fig:reducecols_memory} \end{figure} From dad5a8519f9386c37e20fdfd9c0ef57c3cb11498 Mon Sep 17 00:00:00 2001 From: Brulevich-Nikita Date: Sat, 13 Jun 2026 23:50:14 +0300 Subject: [PATCH 05/12] add: pdf photos --- Nikita_Brulevich/memory_comparison.pdf | Bin 0 -> 16485 bytes Nikita_Brulevich/time_comparison.pdf | Bin 0 -> 16430 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Nikita_Brulevich/memory_comparison.pdf create mode 100644 Nikita_Brulevich/time_comparison.pdf diff --git a/Nikita_Brulevich/memory_comparison.pdf b/Nikita_Brulevich/memory_comparison.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cd5fcaf5082e6a36f0cef3e377fdbeef8c3eea88 GIT binary patch literal 16485 zcmc({cRbbq`#(T`GcTqg~!`@x`I)JOAti=l$EWcs{os0^@T=ZgnJ)LZ}-}0B^K$d{v;pQr z;2#)Y%g)x(O5V*E7!eBmVGxoMXh{qVjshbQXbB_+7zCmKOb_V83yl52q@1g(8*l|9 zG}tZ@!tGx&)UJJq5Q|1Y|{m?mt|*{SfhZbwSRGIR!h= z|Ip!6MVSn?ZuQ&9{jQu%kIjNFD~XuPIh}8)oxV4B`Q={@nqR8U{c!YLXZVBXh1BgD z6J(C$vG`le0Aj8_j28%VWX07_kSExQbU%@ z1H%cc%a89@ao2&Th1yQ2F&;N@RC{xFj#7f_T?xJ!qi%{g^Q=kcu{$&=tMaVv*zM#u z6z?~h4yiQIMTlKbTq@;i5aKOsSaxnelks*5z>LSnWQ$}|G(QX1d3Q@F7TJ;TwLtPJ znKa*{a3mLwi0Jbv3%@^I7CWC4_Tj+!n|aAR*psAO#|^;=k1_Y(~iiOpbUz z%BG`_cq{MpQTpmgdF^X9Nvo)HJl$>xRe&>!54!-ggUzNV)W!xg^>TRRFn0VM-_W`K zy&3h?jnPKRoT*&tO?##S4b5EyJn<#r)5@-}lj$o_0@~$>`|M?k zd47_&NEA;f7cPMKm?baUm0zwO%&~}0*7sQUck0V(JS92*+~J)^6)bX6{PAATqk=wF zJ?x8<<$gn1N15(tM@Qxr*4Y-(m=+fGpl>02sAk@+7x9tZ*oW zhekAtx0IS9BgtOPB9a>%H-{<#_ed>-DUM_W}+m@m+twCql(-63F)XPFA9; zE-m}i{2*@{ujf#{gxs>d7nI6%xvVi;XV|=DNy7KQ`IOnriVf)H#0`&J)?DXvh*$>& z9lY1g?CIrz`fqbbBKK_0Uc$N6JX&2spYM5QMv;==@!{f$5=Y9IF`8Z-2mMR!chBze z`c9Q9t(vha)Rlb({UvMy6lf}fU(y|q*EwNC`f0qj>iu_LymN0SYSt`1GliVKuxdcx zJt#u2f*FSgJ(aG$y{K8+R-q$ZcP_r#MMDB#BW z$a~(D_laVl23!H%h+#3`xPS>)#hW|%wsA#wy1Uh1aA5klvZh~#kEKLOO-p<^RvmZ1 zTexTxe_|T*_Q=eo$Y*#lzL!$m&ysYj&xbvX`&2%2>$GZW#Fe;$8*vDh&c?%mhYM=Kej4G;P$enQ``4_QftD)pBv!vnj`|G2G|f2fn#r@bq34{~dejE*W;1kb?_YefSoNDK?NU z?)ZsIt)`tdGx}gwgUpK^%AJ-*eGj@wvpsEIS}%}ayWmmX#FC4x)Zq#Byu|l$?(@4- zAH+{FT*9i{Iis$5@zTX+6FYasHrBRN^rG({fF3@i9kb9$eCmC=u1>YzwjQ}5n z>v!}G+go6kUdGbhFH(*^z(srC5so2q8Zi|jpKw|JPG%liqosjS7J0}aZgaI$YRHLk zv&3<+u_V8`T04q`B8fgR_O0!HdS+duOHcG{~E?ZctTr_EgM*dY3#PvyJDk*XIv#22btb z_+}$@ZxU}aqmB&BMoqb2I&|qRcX;*G5ao@KrbMm?`O?!qhm?_lobS4od6@ZAUCQv4 zdMwilh{~xeUGO0pJntnzR@1Oq-s&-zCv4JG<_u9Nd9J~Wdk##X=#yy5i{6@k)%ApL z+-X`X^eTG%P^Vn4SJyhBbw-0#NllJ+UWt@yiVDM+)Vy&}jBR4i6Kx991J=_O+z`=w z6F&Ek-R7E;siI|DcCSh2r+RId-Eu9sn3wlh=TKBQ`dDETC3{3KX`?f(g`i&OXww7+ zXZ}LxrYU58?eXcgBaD6aYil0vFCLyOvwd(Pmo^b`mx(LmIu(W$8#$sj?$Pk>yQ|#9 zXLWN^XMW5lvlG3wEJaE46SsMbm=d~uuYE@*)=b7LVGWe9lchJSdfyE9L(!+jV$CmozOX+ey4hHMb`%z{Zy6)cf~cGUl`*8Y?GXy_8(9$V;}yIXs>|IQ zzOoSS9=lrPi`6MK&ATNM-eKe#l5&2s#G}yk)A_D*3=1Vbbj6M+b5^JDvW;u$nfWHR zpvmS_8$$hEnXnU9tnjL#uJoW#W#4+WK>eN|c+egHA`KG7I^=;cERFNg6$0MlUj5@73tRmOb#G;;^pP zQ(aB$SE3SAf;0qw%r22Qa8=mGps;U1UZ*boBPF6Gt+e?185gFrPwM6-kOoaYomA@d z9Hf=?YKQ9Qt2J z_@gymd8?njek3^R&CO%{#`tCDGhENDGA}-y?YW+xX_a?zgQDK_)0JyRo940-b}Cmk z=VZ>cuO6fIJBQn;Avhs3{U;NJqmch?k6L<1T-%^@!(N~hqognU7yWQ-`%lc>Ps5pA zRghIqQ^IL$h<%JrCx5_LEgtYl@MihS==vgS%bS+oWKHc2o19F|wo&ukx(hVkyd0l2 z_}>b4-;4Tq_+SI%>D~`)E61PDAw4Z~No|76;eNUu>tUMb?FT&q3gk_Era8o-^>{8j zBusxcH{Fi|ADLG_5Osu>>1CxPII~STX}K61+N5wNF6=%2vwFJnT-i+m(^@6N zr<_)fpEh0=>+B#`=?m3~vugYH4PifZgyX2WRot}5{iP@*oYqH*{nH}``reG}zG~b= zoXMPc_ngBZ!}k-5fq@oRjy+I1o@%Bb0o$sWOlGDXB1*_Zu|5`P3otJ#!h#gD$x2XdX7+wvowbXjw?6u6nk&1X?8HlcBoRIdi;RENjR00K|LJ~EI1SG>DE06J+wrT2 z4{le4vb8y9H)>K<>wFnw!Uf!)Xr!e)j=W}@ioY8$U06q+IwE8$d@TL!6OSIVN(KD& z<+OD;$xy4ixe8qk_3C@H!(2i>%S_bSs|QAnk;=6u0`EA2+(;}1L$t~2udvK0l{!@@ zQgCz7zqm~8G4mK-kZUDa8n@46**Qdgl9fRzLBRbgg#Vi=Y9@NqDB-RR1zLG8FT?t? zJ(S#4?Q)DUBgV?ApHQbSzGl7msQnpKTM9YKH)`)?N-AgWZe-%yXEj> zjpQb@LoaS{J(*91j&)urUm3~IZpo7!Z-}@jl`NM*EoId;7AuC=cT%5EjD!Xaj@zZ)GUO)YCUXsVV$*7L-RFtmjyjgtIn=NpSBdwWS!0sX`pvKiXqb z+&yhzbZyUVm%|K4r9v;!Xn*dxU74tE7CWPr`eEeY;Uk0ft*=Wt_at%K6Jd?82LFdO z7!v#6yvgV^)04rd*Bw9*cN|?@c8N`hXl^jWMII=SVe{IxIswLC7ZWx*FG|S zLod)Uh88t@i5k#l55#JmbUn$$J)>y`yP)Wm47!%*3U{o5zg6@*VUvf;8Mhv9I#Pxj zBsCK`a`?Pqsc5el69eoe#)`t4&vYsOK=Dc#wm~N)JMt<^aqsu^`r+&Mf~@SJ$BE32 zu%+`<`(o*hc37MLB~42pu2`f67-GCmaCX19q>g4|HO6n{#Cl7BBFEPSDf`@(fy z8Ps}04CW)>`*1FhcZ*ml0{X06P5*7O=v=vpWORD3rbRb{aF9b~xP+dv&(U^SODrpT zDd`Rqq!sPd*z52%j~=--gaPG(_7ODKSB3!E-3TO^4C2h zV$gmf^CRq${4>AZICTX2wk}i`iiDCSDM!erCEk#a=1tEH!6rE7B|N2IM(RBxt)dG? zsxl}m*uwAjlDsXZzeHqo!iLU2qf720q#zJzeW-3ZbPvn5YZ0Ii?UW$lh~u)2wTXrD z5}YPUzwYYK*e>j)gBv9hca;fP4qg@8-$ zLf<&7D>-2VI;0?7U^vv32N#*JA4DnDYv4ya#mV!g(I$T`6mG3>dJ-F}Wl$>FJBi`D>ky};PZ`9QxWwuw_E|*3IDG8!T#*f* zXl10dkj_$tiqXAIQkz2oF+}u1Brk+v{#zYe_8Hv5rcjC`+5drzNIruglFuNJyD&cS zpPJqP1%iXUhvx>tsuf>?_Tj49WO=gL-Y+JJTPzj|XNd2Y7^$;PU-SNAo+xqd_&e7H zxSCRHO@k3%-zPcK3-1FH-|2?!*O(D}3_(9B!z`VjZGP zeQt_7t^HGZvG`o!@LLr+moD~ON%Yev3A7GoL#jk|&WU?eGG9iRaIU~NuGVW)c zj&D1@NGA12Njb#(0>Jj|r9Nx~?Uul;+U~>6B|O){ir-jz4g{$P*<$eL`nZaWYEz z-tno4i<#@P=DfA)>17 z)k3y?Nqhy_n9MD$CShTRqPBk3GvEB$SHJi*ZjzqJHV-8tMk0wE99V_^cOs`->!JjB zv=KJ5QL;4e!6gCeUfWG{L74G{1i#0Q!W!`Ld|o|`Ct8gwFqx#O#nq1`%KnyW^_A&r zS)!KlFB6-Td3~T5dRB;R=050hjB+e@ox7ZVx^`~UBFmaofVcnD0h`f6mq%D;MLNMy z!J-T^q*c%700pz9VTV+=EW1_o;wxO8fYDXCV0MOwRbM5)8FW1s7%G*INTTR~DL)|Z zT>dsG;Q8)&035@=%XVcE|Hd0B#v4}0ghq^Bkh7D5bCcM1o# zJ-q*bD7J71h`g1T-H(!rfu6F4o~WXola-OTzLl#NL2{m6c!g6|o?rwZM@_4r7Z?Nx zLTICC=VjyR=#F>u1jBv;6#CxQ_$>g0Fb0sfX`XTJSV{4?~(-wLSRl8fIR>}VG9HSL6lqpe1HIo z`~hQrkw6edM|*oa0MZ~}80K4(@^ZJb0pJxV7~)RAI-Kq7@jr{6jt-~rU?i|)akuky zbh8Bmcn0LGou?ZZ;^qoW3hx7y@TWZO>_8BE02cv6>>bYlbT5Ekh?m_NI{>Bu;;E}6 zP#Fz0RRr)6Fhn2N_yDjAh_RzB{uIFVPvFPE&Cu0x3)q1Dz<&NB*Imh6&dY`X_+a5cUP~B(a3Kyy076i(a#yw65(yLpG5J*l;3NR( zaR>_Lqnne^NYYj!G!O>b$+)4 z*g_-FAmB^*-T5W-O`!iDV{E?%Fbdj!{r^-(ptkL3ZO=6o!N4>LP#2(j*iQ^>%TTuV z836K@?EnwJR-G+tf&aw42xbP~G7we;O)$>rwb+gg{aU z+yrgeCHyBVKdc^5@>a7gBL;8f2>?F?yWR>(KzYmDfoGpkZJR|B$!6i$U98e9^t9YU zp>+2qjMoPCi-2y=Brx^9u)us&usNb7BWtZ&z?{d#@NIpNW~M;tfzG+Eu4Zk|8&{n2 zWdz(@ljzS*-qB;2aP(lwZIRoTXn*zgvN=Z{kGUudTyo~4M~T+43zcEx*{y^1>}TSg zrsuUuWEZE|q+BQm0#964MP0lzg2`KOXELM!`8%z?8cIK-sCwSdQndGu<*M!a%{3Eo zd5%To_oOVg&g#@jGsM-yjChg5{!*#3`QN7|Ca1sNk{+{WupAd?U|DH0sL;z|Vw00I za@S9|k+ty!i{s^0<+o*Cq<%wu(snho6Ko-Lm9;=7Dgh!8Y+fxMCR7gslJ0xdX9d$J%Z;`qApF-P*F~&Jo_*%=2MDC>n=ZuYskp7QQ`pH5l3)!Busa zs}3nmZ9kXgOLp3l`>OmSK7Hj12iJ}3Mn|4Pv^2QGZVNP{pgA-wUeWi)^FTfmZXnb|3QkYL$=C z%#A$fmu=w5`PE!So8Lp|m@;njOn6RP`eT6$fyrs)(;iCK6T+DGW(^`rPV6rl&t)$3 zxZ&VU24%+IQjGXCY~Cbj#^fy)d=f+{4=i8h$mLY@CoSHaj+_u>JMDOu|Dr~Po0e@* zSF{Bc&8O3+Z2K3;S#G6Umn$vJh1*?F-OuZx;-d1xOtLodBYDV5r>w>PJ*fxJ8n$00 z;kkK{H`-nsTV~wu) zELhA&Utb`NGyx4qg+6EEx=QL!sTf3Q%uS-}!qz~9n_qE~kjDJnK1D!xu^^Pu({KfL zxrW!-8i4irM3*1@aGmPheeoN}D(EAjWBLWR#h?|34j3Kwc>(`c#mqHtvBuTtfbe-Y zR6a9**_XkbCO&xKsRL?AFWRA2DGu3%1 z4uNL{8t11=A@gtc2VE~)kYNKqn=*5*ytaANSH6`F&*`9dVL$C6`#7Uf=Uecl=*#hE zPA>D=KR)+N-luu-#K|@78g6wFfy=#qLI|^Y|FgOw^G`L-XdXDq(r6QPk6!tGD)RWqX82UTyfEk({pV@UhD5J7Aa0Q z&XAd&j_WjTyM@saKHwd`i0kN0c8hv;$+)g zyVx9&(W^}aK$@o(6dI#9uOAqBb$oR8m`w1ZGoQ60GfA$Qxk2^2BIu2*MVoYSR!F)| z{?y{}+;xgV@{o3%n)jgKYHE&k#KprEQTmZp3b(b^9*Fz52Iea;bg|)Zaoi=V{Y_pQ zs7}+e43ei_U*14Kr_5wf-98a9&(kT-T$2OhoMe)_`OMZm1-tx^F2K;OEP?i|;2Hgo zOQnxof;LI-vD%3>l_R>JX~dF)a*#C%p0u#W^Cu^077p$Yu_@6v(Y+B@_C+~TkBgjX1i#WvOta{ zZ4;>;t7^vHoQ2D3u)UUu+KtmW>4W;}+<3!vaxoUViQBANnErmIui@AftaXp-EcoI_ z>1V?9HpLb%KI(kX9$2l^41oB?T7DkaOzmH0bN%9=`!LM)*5&JL`%3A@Cfab*RHhSJ*qW}DxwX9YC3L0X$7YSr}cvLnHK8IF_un5TmP6S)gU&eQ{oxVp=V?V8Bh-; zOy*-24t$e-4My1v4wfUGW6|IB<6cvy-qjf;KXZsW8Y7S#k`^`^c`No*T0&=QA~ee9 zoo+!zQc_h&d3B)wl_+n0<&w!&FO|lQ^UkEV+95m_?y2Oy0}%RB}+&h>_P42 zA;K1s>=3gHC=eCX%uK>dO}1$uM{^ZC)YZ`;b9-}+bei8*$hKEC!9C$1N}0VS(#qMa zDLcs?xA2Dih9^8#gLCzqbr^vf}S$@iW7QfT?zEJ*!*{%x+ypc@fG1?n+1 zmCgRs$d|7J^0RZ?n2ip}65*amW{25DVkZ-Gge4eCt>~}a%nX)=u6poX^xZU~z8n$Q za_$uy4OQEeMbC=`+r15wAuosWXx_yIxF=i)xPM*i@CuE%PXiXICER$x|$eQIo0Yi4@yK)Bn>pBe3>8T466KuSWzKKuX0IN@_aWhfou0&HpX9Ox&*N3+_qXx& zuSjGeF z^!%rxi|aj(1v1(7dSFW|*!9SYZTY}M*UgdK6w*Bj)wYQSaEkMq4M^q*u*SkmAhFqO z;iC%@eZp)?Jrc!N%vU{j;+(J49tbbxE1UTf)u%6E{Y7&*uMb)&VVfc0y&;iwLz?>z zg@5Xf@yoCC=f0lhDw+}t3Rz5mh-{SNOI{CevsGN)cyPzq;H z)Mmi^lWeCItpuGaZOb;-{XebLpF3(eVL&8O0UNeE*7E3GcvHk3s1bk?SCRub?V(@J zO7>_}>Qg%>Cp!E0!GNQ>CYx4KACZwQF;p>(kKiZ9SbFp$v1^rgi7U_z{oy@)-1j>#kPCsQFZ1 zF;Rb5XT{0u(O3vsV~aYH7q7mT)=JE#j#KvyZT#ob@u8AUp|g5gPVj|etlD}(3t>64 z>tu6yxsN+d0NC;VGyOlf1b7>yB(JZmE2r^4ASJ*F{YI4FKhcS8pa$aqM3i>)yeo9$ z{|!+Bpo6WA^I!1ME)XSPPTsDLP$aN}|D!-y7j01x!238q3cxEkKMKDp6C&9b1qmQ4 zKMFu{{G$N8xAUVi@M!%g04LM73cyj?pOoKqlzvgd;TJ6@uU|w?hM4TH7sHwL^(OSo;4Ntik{wqW}I7t+M*AV(a0sWzXWc~M1=q-!;CB0u--rE1i{ZbnYfW&@i;m3Ui0(QBj zl^@qiU_gCaX1jF_7$RU^f9?aJANf;@TlWEufukVX?jyj!VdOvUf!P5F=(hWk;H~xl zFMa^#09bU}eK|02ByL-KdGOZy>UVtwFmR}BTYW`98r!dx04Z*7uM7qR^`|~CS=1JP ze{2=Coj+i*TQMBKySC;BFpt{K9}?hayZn&KfOfX}-==jUNdSB|e%&Im!!;bt6uv6m zCg#Q|88tL45u@f+@6mJR#hE^QE|fbdn%v{)785Ro%Wm`iIBll+6p7OL`0XQ$xTgPu~MEFu%!`Hdm>ZE zbT;V~vnwmPTC_}LSR9>!nXV%*b$tQ&Fb-GxXr^o}bHwLie48+jMer|5w$&5r|2O#oacCHKqZ=Fs6Ohg$D-ij*QJ<9e)h#YLY5B~jfBt$_D z=nrCJ1sr(;)CiG-|IccGYx`3T@jt6UB>*@3ry}zIs0cWCpdwTP0}Q>*b!-cce=KWT zGX96S&D#DDw=bH1#MU1#l0q~bZ3#ygw%*vp{dm998^GwdCjRry3-tCa0R`Y4Nx}h* z!@x-jcV{=ev!gZm3_=11lYokWPvPw?L25@w9RV2KodRS2k4uzwkfOmvpp%?^K6p9dnLWP94NygXH&K?9f zQaA|u`vbT`6rg!~@NXL7I0xYacKt~Mj@lAD(LXda;c5SeCJD6qmxcjc^}jSM;F@>P z2v9oV^Lt#N3@m#8r6CAjm+<*h4>%x#x6b?W(|Ipw>+M= zP|ObbAra6WV<1t4QwRUF-Kk$F5(C{aHx!&04LFkUPk$&$!W&3`kAdDfUl;W>bAI|sp>G#)V&j7aft8#A5~P3qm-+Qy31qs59Oyv?aCGCS_pkw|+a({2vGH{E@~{HxkVFVhO0xSbC2fV=(B)UtYl#7cia0kV8-zyN@ z+3%R2#rkhQULwYI^L?uqrVv2Z5!$?P%eN*qJbbDud( z5akl*6OLedpAZzJ#$V?$P-frK25|n2+#*m;Flt zO1*vYjZo zb+qif$`Q*Vvq1e>5wFW9waqNQa871^wGp)M4TlKF^$op*^Y)B1qAdubTc=E|PPhCh zjn&E+e(dvlYjEqOP0`@vM=XI_{0Tfu!u=1<81^?EyLytOo0?}TxQcGwoMTyL{gRHk z%+Up4cG^cbxWx2gs$O9dgX3cLc%fPYlDFifm(``iGwyKu z)3Pt+(fKLm=cDN=E2QIy#g2b4tccQrnW)`=pEUjG#>0Gi4AZoaBhsC^oiK}qMyO52 zusYkQiMRh4S9(V}{ZX+dBKF}%U1Bi`ODtuktq~QwMo8!P9O#cchNciVQY~YRXEDXy z)ZSNyDr3qe{Asg%e>8?s%uTSdir2bbl|59MEIHcD+n?6n2j^x(q`293dn2Ewlb?^v zATlDlDQkD)T;%Daqtg8`HKo!Zk`LjXwJ!%*&PMf~xlFCq#CcZ~X7&9p&2-DA*W8`s zJ8#c{Fb^}i{;#d2vr{g1eGp?h z4`c!NTpc?&zTNH(_)Y8j>?qk<2)~a0;k(k580#p}QO%C`*WYrrMyN!0ncs~Mp}()e zME6)B#nMl(m7Akl@&~lGBy=K_jZ5fRUPlo@bw2e^(*XhH(jyB%+dSXVLK(xay#rbW za7QBuOkpFUn_9O;fBtL=jamCrZa~hwwDHwdTGN>J);Aer?ah}?R&pNI`AW}yOG3w+ zuEwIJgYmw2y=OQ=HakS*@Z6h)UN)bL+p}GlJDucbR?Aj@v?_`>u(ng(H8fQuKlQNr zUDuq_7~Px4W>sPmfzN+_TS$9)Q$qQW?WS(SNd~eMPxosV6zbk6_>~p0qcfGpFPk`9 z7+Luddj7n~upBz}y@AhnA?3{=Yqr3u``zb$cEy+dmxrDCzIcx9etP!kc|mymwzHmH5gwImKsS99);kYEz0*w3>pG*2xf4^Qf2 z!iww(n+BN|&gq853>7UF@;mdddXpkQ5oZ}WcG1S>N2zQ{lJKU;fLMKHz`ZW*QGWV; z%RMKy!AQcQsaMxoki4rY4zE7RBUv4d9li$%iJd;i_>k41)3}(&I07@R<>P=9SoL;5 zeIiC0JF+^IbF)o{w2VJ?YAp{`dHJyI!c@h_K?l9*`9Y^{3Wus!RfDQ%oo^F4WSu?X z=}XSKFT{m9E{tv1hP}n~ydJx4Yvp{WsHbkFKq5gSf!5pCK(SV-Bc%4MzHgt0;J59n^LR=OcY>TLd zp<#}T={jsH#b3+l5f!n$Nqwohdd8vQ6~eV*L`5UU;J5Tz&1y8aM`ylu8OD53k*o|7 zcbhfmi6NV~q9SY^_n{>%(N;aTLj;5MjQ;ez>9hhOuZzn{t4az=^ifmkb-bDYO`Q_7 zS3!}rT3aT4@xcwxP~Sx{Fq)g%{b9GqjYi965AuB7!)Mpl>1u1JtY(g0-v)qmBCsE9ZGSACq-__?G1dFz+%_eEY3(rNPO+%a${h2et zLNyP0j$fuYGee(GSK`hlpFq8ypWgT zl->22Pv~+d^cy$Ijk=n9;XwpJytA5yriI%b;+(uorokUecs?c*2(X<0=}nu7^jaFmy~+Kpkwl8Al$dJxlxPsM^5VJi|M6MW>;E zvEiQf@cCCucl*AaV^Lk2T?!dI&pJqqc+`Kiq~Ly|@@s!PSWx~$uWYFIkN|4AZ||a(}mV zxkQ%Lf9MDINsD4fwKb{_^Am)))aF-A{*~nH1aMqXhl;{Pe`h{BkssG+3^M(vZErgC zJNl!LK*;}(&@T}$PD{u^F5{=3%Q-wwmC2i?8r`!sYVcNxMeu z=Sd`^8xLPcI|{}c-}oBE9vt1IFFijF^=Dm0OVh&3=SWK_lUon-`uo0H5_-wOT@<3p zG7z@5bj>Yx{kD&&MxkNeeg3c>J(u9?SElc|7aA^H>AOt1bnha0u|3k5&LOOHt0*-i z-@ux5y6M6e?@(U`^t_o*4SEreSn%XJaKvA5E0oyf+yWsdS}eXoAqcw6{jx$TUS?n$ zDdS7kmd}^ws#tr*M!B#a!M%R{xUiX6;*WH`K#^kKiHj{Gm@2N$0!!s#scZESH}l#U zO5;BazA0^pxbMli(n^8FG$+%|(`DtoZ2Nv;RYYVqDVerTR%3kRY>{xkF73s0AK=17 zN6--^MJ;?h>v7SgLiXJ1+KUNt#M><+4rj$O3OT)CN<%7%D*fNauTtL{Q0W&fed>Oc z!LmwAaXn#3?x>&~xIXA});-}9Ieb<+g)fJtHEL5o6T_QRN{VlJJ5yiktX-T!=rmsJ zJ*rIcp!LGQNr~8(3GPCT@K-bsonwON7Fg$2vObXa8y1hQ*>-Gw6?ZB}Z)EhQ%5-kn z4ZR8XL#d2;DPOuJ9u)cZ?m13Xx9zJK<)YkZnh=7Mr3pO{k&9?q@evLy8CcS&XYEOTE*EG~imr&qGhVJaund8D~x zie}Pqw%0j%)i6I>nvh7(C&-z*hOkOQ=38oZXO>1`v<)#Ok6tNrx(ZOeks!MmY!B5C zHV6wSu&`uBO-n0?Ioi|t1$NULD?1SjPkPw*Xl)$YZo0}8!el?Tpen*}MVS@NBfXY7 zckWyDXunIzTylQ4kY;t|_z%_QlY%pI>~Ef-%aGk(5u7 z!>FqWevVB&@|3Dd$iIX8?t``Q&1Jggx6K1ds_I)-*%_*>z?NVJw zD=@?Yb?*)bhr&s2rjld4NtYVS^Juyb@iBY7MNt^f@CY4VOp_mR#$>JXs1%$m>nhI} z_`W`G6Gvfrc5Ie8Yl!gtD^3I+I&r({eRRTMf8k+~7!{9J2+8Oay-5!Ilj}|1EOo~D zt?FdOS|6&IFfO-Fm6YqxB8se&v5)*`3u})gzvDIJJC}N?)4kuQTn2kjOieD}fnzusUJgP1-rR5{EKbA{GXU!E_S$ zxo6mdTnp}!I97vIr(or2I!d{CF1H*o=MP2XT=ceH{39zOlspp$RI5GLciXy~End5!QSSM-0eb58h$! z{E`g$*ckLoM1C4e^5b@vi*#~)nOma-m=DD2VwCzvgYDZs+oG?#d00WoTVGhO zhU$)sh1@u%{nsc(}urh4yoYg#I^o zNR1kRJMuXs5hF=XUlrn72&mO&8T+a!4f#6`+<`7`y_$I2L>Y1sROE}&nfu=?aIT1wd60JZId(;r9*ACn{YXBm(cPS zmRJ=yo5gJmYgyT#$DDiwD+vcvjU*)dD+3-o6-^@pkq5;dg?NAw2xys$~24 z`x~bYM?KVpXhIMW!bJIS$&`dU($O5Lxxu3G_IdGLL^KGkjzbmXK?p@kc^PZiqXB~V z#S}O2%#J5%75R&h0*9ltA({^$hiQw7!bv~15tH(Tn@Bd)Bos;uGa8V0bRMec7VHid zL_Lnulcc&+qoS}Mn@a6b-*_iMv% zNz5SL8|fnQvtemMA!35KPF+``Mq#CmjR>21R1+oqdo~{0jUG~LAk$nbK{KZo z%Wxq)?T^XIhVgwk$yYix#pkL@)`@v_Vk5wTDgA|LYZSa-7#UiSo#?L{I?S6``X;*C zmX}C`K0`mlgBlcAt}$dW|yw`d5AKvN9kWJcj99|9q{7L zkalZ>{i+}c6}=AYjCmx-ULQz-5odHfdQ0K?oZoRdm%g)U?$`R&It?+>94TZ;UkmwK z${adlW7Tv@L~Cg9&aDA z;_;6;s1G=vG!lybZ*}b0XHYY}ObLR3{SzUc1Qm`apMfL(!uW)KX?lw^02Jgkx;O$- zEc+J7im7OoWXqzTTuu}+T`uHH6Ji&BS8JKN;q}cpLHM%C2bU$7l3Yu5z22#p3sQzr zlL7ZwI3-z(2XxgH*^(4DnoS*Q{p}+w;{t?a7JR;j>1xqh2FsINo?%I8TX;|`v{*R$ zUV+@X@A&=1{ClSZ*5j?>T4@%J_^62oJ)CB@FP=D`1APV3E=~;pR;+A z!>aqT;@_z&ebXc#DlN0l3wdPBO3zu*WmS-<{ZYtV`1=c6k8#lHbYdYEpO1IA9Ivb& zx=wRp$;QoO2RH^3>adXL=_wT$|O0zL7FN zIDH6|oPs|6k@uda%SNI?NghR@#sk&mx(Vv_iKi}C*&_M5h%l5dLtnRUP9Gn3zd<8W z!;;bzy%v1akW?fOeWvJx(U&{v96lGd{P>#_b!#G3xQSIOweoE*^-qC5N{ch51*O+D zdookbe0o;H`9sCZfv7;ElSu< zO9UiBdp3_GCvF{;`1tCmGkI#+i}A5~T8=~ON>8?4jNEa}EQD9IjxA-`-n&*t_)+4% zS|cBy-R;&PMeiTJZR_8B8@3Of&oU0dBSt)l91JKc{AXbRsafMJ2Y9r1^hV=^DPAKh zTqFb5+o*z2{it}~XZCz5u!(#QEtO8ShBc@};>_~;=X>&gW=eJCsY;mwX4hUNG|F>a zgrF(tz>*oPkkuIZSe9BhDeYAC+{R_v4KaT&znK$Oz;^A|0Mc)B}}&dZc&t$26D62NQpA zLP|nTl{|qli*?n>wj%_Pgxu4TUv=^_x$WBr7Mah?Or0zQ>m(l(4s>twvWq(HKuKU} z3s0NfD~vt{V`L;CYvW*{=cR4o;)#=-hbLC%f`tbN4#-i};@1rtP6}+pT(Gh>o>m_A zZdg|j5cC)3r0r#i-NCeQa{zgpx`i`<3>|p&?s(~4G)M>vfk8n+2oxLy6%j=MSPmSH zgM)BWs99h=>~|m|VF(20$bjE}u1rb6IN~$`Bnv=^c5p3Hu$&73`rvS`Kls}3CQ`7h zy{)YcfKuULDdQccJl!m;0K^Oe0=wbhD<>OU?5|4?d%Fu*5CYh;xY>BvyIO+)kP3Xs z#={i^c69-m!d?WfuopaRY)HYj0MrEn+uC~r?VbR=U{4!w8y67RX6GGX7kgj;3K%X6 z!X>lXKs5^hrNH|3*4PUGwica z5T%oaohQKWU&&p{(+Y><0d+WlU_iyV8zC4R5QL0{o8m4@5K^$g?@ItB1n^6HD=8N{ zCmVnjur}7lSr2!iX5q8LBS=I9vKK-8y;1=c05J{)f&9-uxF`gK``h2=pK$8|a-ewhf)@L<1|+8=ubcB?z%c3O7L7WQj3{4!l2vD@jfYnHHI#NaFy zQ1b4RoprF2g#hI2m^Gjr+%wW0O9vdlPQRT60IW~k%^v&2lU>6Awf(2>HPupc4S|q9 zp3>hKX6Gk;_=caO;7*;}a73GT`lX{%TnLn5J&76O!5_&?xS@wL;0PLP&jK^$dN5`13XX71c$Z=hw5%DO`FJw+9lINGy z2_(PH9>3%)KkT19DqE>P)!;5oXU;pzLQgrkP~!=H6B;kKQl(We_rU4dSN)|jbm*y1 zzTdg+kN1`&O^d_xZhK=LZWD`DO6LEZX`h&lsH`8iq%@o0s;6FS9JDV)bD-sj44ZVN zij=>mI=ZWpEFY1(0&6Ct`WW*GRAPa z^zDm<4|iJ&mueq2jW&zT4Y$6d>a|H`JLt*bcoKIQ3ijWkmcTqqXoiq)){&+(8e=3z zMxJqwZeKhk_N=`n@)Tv~V`H7(wp;gY!aA>+dZ);`d}Dp6c3xlS4akd*>vcP~exzaN zN9A~fhu71F2ky9p_2%fkr#L4Hhq5Qi3UctSoqqa#L(IptuW8FGsrN<4Mvhg;KtHFx z)Sd8vH%3u0h2BG;%^cmQtoP5t=i4X^#Ny(U(+6it^Dm1_$4?#&KO7=!aCInWjH64s zQ|fWnQe8n;0jl`xU}rOB!YAj#YdTGCy{e5>{itrf!)TL5jPfV>T}N< z9Ugxu>Ab}O3+0D=miT})nPx$yhEGw|$A57988*aw>c!8Wgr>Lb$`6VY@cak%g)m@^ z{-@<4HO1qIpd@piq{0s{ApfVnwri{Dj|1zN5UnH{kSY$B=RBU@E%MQ-xe=FrvvfQd zzZ)y4bGq}MlgDg(hh?{>KI4iCNJ=>}>n?XIK9rg%a|C|xJp1j5T$)1nJ9b`#5E|@# z+3+H}(J-FX3eNBc{hS5?Yf)vN>iqD_w;TX4K! zJ+yR$_I|461G$yOFqeHdo4_ zcoYm7@`9Q<=a3t*Y#^~d3xTFHeLWs(@TALd$X{%gB(zjqfcnqqCVf4ybDiq*g`KWd zTzn#Q2T=j(;60~Z@K6v^#&bgN^un)Y z@DuSU`KJG#VdXj1#~F?LS7KD4{M>8K>Ty~wt%#zb=f(WRsrqRWv$Ju%`mOiT8hj_b z!j>^T14*ut-8b}WTiNZhUg^d4VX{r04}l4{vBY?U|2uT!va8?4anxUw4J5Q`5&%4^ z%allE{O+w2@5W5V=g&z5EjyjEl%*laH8R$z`fwX^Cv({hwzz6h!uV6*bpwfr5KOW{>1L3#spmRf@|(Q@IYuoZ7nL*5}4tZ-LEyUA5JcNfI6d zZ{fB5DjE9leE1i(UTK=@Y*NN)YN@;3)^68DSKG<`bzMv2$=-8&YkyuT>2MC*KJ@sw zttTFt;;DI}{$_b0VY)zZ2th#0^XU_55zi-FaVRBR^0IK`;bRkSO$8u9I!|p-*Yl^; zQ8okxLL54{Mb#`sor8ylz59dTdPV+CRM8ZT!fnh8FEV43S{j}a)N?5 zDAX`2hv{g1;#**subgBqqpxNB>B0~_ME%Z;fp~;2k<>k;H>jfpIY?^woK(|pfnw;v zn3@T_W0Pp__%K{+HIsFfl(E4wQ{+XSmTSvc8hU7m`g@q@by3TH#d*-x&u6;%D6EQ22S00kQXgI~ zSM>+`#F~AbP)#0MrFZ#er`aCrazFhRJ!=WY$EjA#>`_C0*P>UcH|o9LedtwcJO7k6 zCAPY6ZE+)SbA`f*&j?Qq71%2rh$V3NUw9@VjJSs^5KG?iVS~GG+>Gt30I=zapUzz6 zt-_bug1EHb8w^KL2}~RtMESp_GyGz_5s(-49pv16jpO6fils{);$xnjpBt=9Z9?@x zU1f|ajFwAhyqiffKGOEWTZcXh932sj=@sr~B_t?Jt2%P+)D!as2b)+*X&mRy#SR_vQ6C)?U!r;s_q z;#jDlNE+?nDcad8dpFVlu3+|Zo2<47hmc+;yL}QEs!};YeY~0>?0h}r(whG{v%t%Y zffab{8&85N@)uEFEk=qmNRotbvHl7#J)^<5YtR#4w)HPYIi9($&SE42L4Sgt9O#XR zH>7_nH_kP`VPZ`FdOSH)Fe8?0WQnushpw}0RZ5bu*vWn*6P{!a*is&_7$~s&`_Is- z8z)ZLY)%q#QT;vVm+h#Ks>LDqbZ}~pc-wMrs8U-p(=09XkC%qH?x`aZ*%WV5tBA%|W>En~?HA-nGjU5)l z=ZMB%uooUA5Q!(b6Zs42!r@4*UC&x%+xEw^n(GOt<`RV_6WTJfrV$wOd}>n^j1*J_ zhuRP%hxE%A$!pS43&v-1XI`1^8CNDGXcA+s!$TCFYzhYK1OHR!5}HabfUB+R6W9nQ zC}J30$vzf+{`Tnvi6wCcgDpBmMkz3;?niw!|9 zgNG1&2@m2g0;8JdE=~djMsos{6#sg=D*Ttf3GWRaY~7h9YBihUr^(UDzYpGKQMq zhq0hdm$akrGe%m@ApQiC#{w@gs?L)1?om+{t!g`8*;IBXy|g8a2AD^J+M z^BCX!T0fRsnJxm?V@ZRTug}9xHS?V38(eN~N{=>JKfUwtmTl2H$)OetL!#15!Csrw z{wYrd8A5cX7}96nYJR+^IiJeXIbUYh*GL!AGE>aH@q*p%!;KUz z)GyI`R@Q>sq1?K3d(&@Wt?u$!-6grD1w;LXH-%S1^Z*=8YTzgQzxb}k}rG(`d0WmYV3xUT6hqE^l86~qGmCs3e6fmL4 zB-xNMPxI2J&9O#euBm=Y!GDD+wOfI`mlfvEmV}2kJh2>#{tLG*7q3EzI{~dNtptx+UKx_S{p$tVbHVyc&**Wi$*vp~T{$7R<%Eh8t%|$^@_%kLpodHm7PDPB;#j2YI%I&ol zj2!L_h2RbPNb$UD%1mSyf>yPRns3RjeJz=IeQ%rhl9rkSZ0Q`Gx>n#)X!iUj;UZS* z^Fb2;D!qU5ra$#?&>lELPESEoU+I6q8GsY|2hD(r9zZjILheqn6F-`9;LU$kRsVlO zGvGKI2THHMp^LvjGXS2vT;nIBtwVDB!y)6p*l@fKw?V zz#j^Lg^&PRgaSB5p`joVU?38x!lM8v4}}Jh4hRf{1p12ro(~Bi0Jw1|xF{(KP!1Bv z!v8riy<95WxEn*dZPV3kClT|-*o0{=lGteI)gPP1Nky7X{xP0$ zs&ONg0Zx_6@sGtg#a1Ewz;O#(ufrCNO7?o!LCIhIk{c`+gu1TOj51vFysOZhPF!C7 z+@yYV9GhU<$VyBway4oCdiMCL`~386sjn{%&W=%SH z9xIb_x8)*EP}#-CmOKh17#56+#^c=qUHvv#c_?THy9RV64+HJ^{k_1`-V{>`y4Oqo z^ED(`MhbWz*vbMp5QRfsrC|TF8{owLbc6rTZV+KW&wn~1{x2N?7YuZS2%~|i_pJLp zsoo!FuqUSdY21_R{At{~IogeWyI+oiRqU;C!1m53nwZ^BD!l;oc8Bp_A6g*yZrWvl z&mwW~{b>MacXM*ZI@w!-yy3!7s4zqjbODQX^ArPvo&R|z?CN31M+yc2cWW;z;4{m; z!`!TGL6#O)j=(g(UjcO8nZVxFMHcs6>SyGO9qwyGAJ7LdQuM%B z1Y8s_@qdp+AaU+|Uz-SUUUGk%sOSMckWd^x{_n9!*g+W}@yG=!0+ikNjYUC$g3Nx_zBbW=V-YamB+S42LC`Rf1NuM%%jrNr^g+3Z0!LW) z_Y*}N)UT)r>cAYLXwm()fjhFZU-nQ43U`{|-@HLY(EI0wLPQVf0}2HsvwtiUc5o~d zDRO`osK|kJ2?ZR@{&fkQE5e<8_&0qp1hB{6-v%I&2inkh{D!FL9-6Tp7WPgy9y{Ol zYujG}4*UR72jl9BbH6*eijs@1D`?04?nE$8tc3@5$K64ZP$Yzun_Espp7j3!Sq%u8 literal 0 HcmV?d00001 From 734c11c9629adba67458e3444cf194f030d62fca Mon Sep 17 00:00:00 2001 From: Brulevich-Nikita Date: Sun, 14 Jun 2026 00:16:53 +0300 Subject: [PATCH 06/12] change some text in report --- Nikita_Brulevich/Nikita_Brulevich_report.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Nikita_Brulevich/Nikita_Brulevich_report.tex b/Nikita_Brulevich/Nikita_Brulevich_report.tex index 2e41eff..829439f 100644 --- a/Nikita_Brulevich/Nikita_Brulevich_report.tex +++ b/Nikita_Brulevich/Nikita_Brulevich_report.tex @@ -75,7 +75,7 @@ \section{Обзор} Основная идея библиотеки QTreeFSharp заключается в использовании деревьев квадрантов для представления разреженных матриц. -В отличие от традиционных форматов (CSR, COO), деревья квадрантов позволяют эффективно выполнять рекурсивные операции за счёт логарифмической сложности доступа и возможности схлопывания одинаковых значений в один лист (UserValue(v)). Данная структура хорошо согласуется с функциональной парадигмой языка F\# и обеспечивает неизменяемость данных. +В отличие от традиционных форматов (CSR, COO), деревья квадрантов позволяют эффективно выполнять рекурсивные операции за счёт логарифмической сложности доступа и возможности схлопывания одинаковых значений в один лист (UserValue(v)). \subsection{Исследовательские вопросы} From 92bbcd3f0d1867e21b42817a8db6ec1416a0fa27 Mon Sep 17 00:00:00 2001 From: Brulevich-Nikita Date: Sun, 14 Jun 2026 14:04:18 +0300 Subject: [PATCH 07/12] fix main.tex after conflict, changed report --- .../Ekaterina_Arzamaszeva_report.tex | 232 ++++++++++++++++++ Ella_Zamyatina/Ella_Zamyatina_report.tex | 164 +++++++++++++ Matvey_Timofeev/Matvey_Timofeev_report.tex | 173 +++++++++++++ Nikita_Brulevich/Nikita_Brulevich_report.tex | 122 +++++---- main.tex | 11 +- 5 files changed, 634 insertions(+), 68 deletions(-) create mode 100644 Ekaterina_Arzamaszeva/Ekaterina_Arzamaszeva_report.tex create mode 100644 Ella_Zamyatina/Ella_Zamyatina_report.tex create mode 100644 Matvey_Timofeev/Matvey_Timofeev_report.tex diff --git a/Ekaterina_Arzamaszeva/Ekaterina_Arzamaszeva_report.tex b/Ekaterina_Arzamaszeva/Ekaterina_Arzamaszeva_report.tex new file mode 100644 index 0000000..af4d139 --- /dev/null +++ b/Ekaterina_Arzamaszeva/Ekaterina_Arzamaszeva_report.tex @@ -0,0 +1,232 @@ +\documentclass[a4paper]{article} + +\usepackage[a4paper, top=8mm, bottom=8mm, left=8mm, right=8mm]{geometry} + +\usepackage[english,russian]{babel} +\usepackage{fontspec} + +%\usepackage{fontspec} +\setmainfont{FreeSerif} +\setsansfont{FreeSans} +\setmonofont{FreeMono} + +\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{enumitem} +\usepackage{graphicx} +\usepackage{float} +\usepackage{booktabs} +% Для корректных ссылок на изображения с помощью \ref{...} +\usepackage{caption} +\captionsetup{hypcap=true} + +\title{Оптимизация произведения Кронекера для библиотеки SuiteSparse:GraphBLAS} + +\author{Арзамасцева Екатерина Андреевна} + +\date{} + +\begin{document} + +\maketitle + +\begin{flushright} + Группа: \enquote{2025.Б72-мм} + + Кафедра: \emph{кафедра Системного программирования} + + Научный руководитель: \emph{кандидат физико-математических наук, доцент кафедры системного программирования Григорьев Семён Вячеславович} + + % А вот про консультанта укажите официальное место работы, с "ООО" или чем-то таким, и должностью желательно по трудовой, не просто "techlead". Выясните у консультанта. + Консультант: \emph{Кутуев Владимир Александрович} + + Старший инженер-исследователь YADRO + + Номер семестра практики: \emph{2} +\end{flushright} + +\section{Постановка задачи} + +Алгоритмы достижимости с ограничениями в виде контекстно-свободных языков, основанные на операциях линейной алгебры и использующиеся для статического анализа кода, могут быть основаны на произведении Кронекера~\cite{orachev2020}. При вычислении произведения Кронекера для разреженных матриц возникает проблема избыточного потребления памяти: результирующая матрица содержит большое число нулевых элементов, которые требуют выделения большого объема памяти. В актуальной версии библиотеки SuiteSparse:GraphBLAS~\cite{graphblas} фильтрация ненулевых элементов выполняется после построения результата, что приводит к высокому пиковому потреблению памяти и ограничивает применимость алгоритмов на больших графах. + +\textbf{Целью работы является} добавление фильтрации нулевых элементов до этапа выделения памяти для результирующей матрицы в алгоритм произведения Кронекера с целью снижения пикового потребления памяти. + +Результаты работы необходимы для повышения практической применимости алгоритмов, основанных на произведении Кронекера, для анализа больших графов. + +\section{Описание предлагаемого решения} + +Основой для предлагаемого решения послужил алгоритм вычисления произведения Кронекера с ранней фильтрацией элементов, разработанный В.~А.~Кутуевым~\cite{kutuev2023}. Суть данного подхода заключается в предварительной оценке количества ненулевых значений результирующей матрицы и выделении памяти только под них. Таким образом, выделение памяти выполняется только под значащие элементы результата, что позволяет избежать избыточного потребления памяти. + +В рамках данной работы этот алгоритм был адаптирован и перенесен на актуальную версию библиотеки SuiteSparse:GraphBLAS (в исходной работе использовалась версия 7.4.3). В частности, была добавлена поддержка JIT-компиляции, которая отсутствовала в предыдущих релизах библиотеки. Это позволило сократить время вычисления произведения по сравнению со стандартной реализацией. + +\subsection{Реализация алгоритма} + +Для реализации ранней фильтрации используется двухпроходный алгоритм. +\begin{enumerate} + \item \textbf{Первый проход:} подсчёт количества ненулевых элементов для каждого выходного вектора с использованием временных массивов. + \item \textbf{Выделение памяти:} создание выходной матрицы $C$ с точным размером \texttt{cnz} вместо верхней границы \texttt{cnzmax}. + \item \textbf{Второй проход:} запись результата в выходную матрицу $C$ с учётом пропуска нулевых элементов. +\end{enumerate} + +\subsection{Изменение логики распараллеливания} + +В процессе реализации появилась проблема в логике распараллеливания для случая использования селектора (механизма фильтрации элементов, определяющего, какие значения должны быть записаны в результат, посредством побайтовой проверки на равенство нулю) совместно с гиперразреженными матрицами (матрицами с преобладающим количеством нулевых элементов). + +Исходная реализация использовала поэлементное распараллеливание, при котором работа распределялась между потоками по отдельным ненулевым элементам результирующей матрицы $C$. Данный подход опирался на предположение, что каждый ненулевой элемент матрицы $A$ генерирует ровно \texttt{bknz} записей в матрице $C$, где \texttt{bknz}~--- количество ненулевых элементов в соответствующем столбце матрицы $B$. Для алгоритма с фильтрацией это предположение нарушается: селектор отбрасывает часть вычисленных значений, и реальное количество записей становится непредсказуемым. + +Хотя данная проблема в принципе возникает для любых разреженных матриц при использовании селектора, наиболее критично она проявляется именно для гиперразреженных матриц. Это обусловлено тем, что в гиперразреженном формате хранятся только непустые векторы, и ошибка в расчёте смещений приводит к обращению к совершенно неверным векторам. + +Для решения этой проблемы в оптимизированной версии осуществлён переход к векторному распараллеливанию: работа распределяется между потоками не по отдельным элементам, а по целым столбцам (векторам) результирующей матрицы $C$. Данный подход полностью устранил необходимость в сложных вычислениях смещений. Стоит отметить, что поэлементное распараллеливание позволяет более равномерно распределить нагрузку между потоками, вследствие чего может уменьшаться время вычисления произведения Кронекера. + +\subsection{Особенности работы с JIT-компиляцией} + +Библиотека SuiteSparse:GraphBLAS поддерживает два основных пути исполнения операций, выбор которых зависит от типа используемого оператора. + +При использовании стандартных встроенных в библиотеку операций активируется механизм JIT-компиляции. В этом случае формируется JIT-ядро~--- специализированный участок кода, оптимизированный исключительно под конкретную операцию и типы данных. Это позволяет исключить накладные расходы на проверку типов и косвенные вызовы, обеспечивая максимальную производительность. + +При использовании пользовательских операций JIT-компилятор не может сгенерировать полностью специализированное ядро. В этом случае система выполняет возврат к использованию generic-ядра, которое представляет собой единую реализацию алгоритма, способную обрабатывать любые типы данных и пользовательские операторы. + +В одной из версий реализации алгоритма этап подсчета ненулевых элементов выполнялся исключительно как inline-код, что исключало возможность применения механизмов JIT-компиляции для данной части вычислений. Однако логика была модифицирована таким образом, чтобы обеспечить корректный вызов JIT-компилятора и на этапе подсчета. + +В результате сравнительного анализа было установлено, что использование JIT-компиляции для подсчета ненулевых элементов приводит к незначительному увеличению затрат памяти по сравнению с чисто inline-реализацией. Однако этот расход памяти компенсируется существенным выигрышем во времени выполнения. + +Реализация решения осуществлялась с использованием языка программирования C, библиотеки SuiteSparse:GraphBLAS. + +\section{Эксперименты} + +Проведённое экспериментальное исследование алгоритма показало, что на данных, характерных для различных задач статического анализа кода (например, alias analysis и points-to анализ), удаётся снизить пиковое потребление памяти, но это происходит за счёт увеличения времени выполнения операции по сравнению со стандартной реализацией, при сохранении корректности результатов и стабильности работы на различных наборах входных данных (графы программ и рекурсивные автоматы~--- способ описания контекстно-свободного языка). Экспериментальное исследование заключалось в проведении 40 запусков алгоритма на входном наборе матриц, полученных в результате работы алгоритма статического анализа на реальных программах. Результаты замеров сгруппированы по названию анализируемого проекта (ось X графиков). На графиках время неоптимизированной версии считается как сумма времени на вычисление Кронекера и время на фильтрацию ненулевых элементов. + +Рассматривались две конфигурации оптимизированного алгоритма: +\begin{enumerate} + \item версия без JIT-компиляции (generic kernels); + \item версия с JIT-компиляцией. +\end{enumerate} + +\paragraph{Среда проведения экспериментов.} + +12th Gen Intel(R) Core(TM) i3-1215U. + +\subsection{Результаты экспериментов} + +На рисунках~\ref{fig:v1}--\ref{fig:v2} представлены результаты экспериментов в виде box plot диаграмм, демонстрирующих распределение метрик для различных матриц. В таблицах~\ref{tab:summary_nojit}--\ref{tab:summary_jit} представлена сводная статистика по каждому типу графов. + +\begin{figure}[H] + \centering + \includegraphics[width=0.9\textwidth]{images/rations\_generic.pdf} + \caption{Результаты для версии без JIT} + \label{fig:v1} +\end{figure} + +\begin{table}[H] + \centering + \begin{tabular}{lccc} + \toprule + Граф & Ускорение & Сокращение памяти \\ + \midrule + avrora & 0.708x & 2.29x \\ + eclipse & 0.722x & 2.16x \\ + luindex & 0.725x & 2.11x \\ + lusearch & 0.736x & 2.12x \\ + sunflow & 0.704x & 2.38x \\ + \bottomrule + \end{tabular} + \caption{Сводная статистика для версии без JIT-компиляции} + \label{tab:summary_nojit} +\end{table} + +\begin{figure}[H] + \centering + \includegraphics[width=0.9\textwidth]{images/rations\_jit.pdf} + \caption{Результаты для версии с JIT} + \label{fig:v2} +\end{figure} + +\begin{table}[H] + \centering + \begin{tabular}{lccc} + \toprule + Граф & Ускорение & Сокращение памяти \\ + \midrule + avrora & 0.959x & 2.29x \\ + eclipse & 0.976x & 2.15x \\ + luindex & 0.983x & 2.09x \\ + lusearch & 0.988x & 2.11x \\ + sunflow & 0.966x & 2.35x \\ + \bottomrule + \end{tabular} + \caption{Сводная статистика для версии с JIT-компиляцией} + \label{tab:summary_jit} +\end{table} + +\subsection{Анализ результатов} + +Эксперименты показали значительное снижение пикового потребления памяти для обеих версий оптимизированного алгоритма. +\begin{itemize} + \item Версия без JIT: сокращение потребления памяти в 2.11--2.38 раза. + \item Версия с JIT: сокращение потребления памяти в 2.09--2.35 раза. +\end{itemize} + +Наибольшее снижение памяти наблюдается на графе sunflow. + +При этом оптимизация приводит к увеличению времени выполнения, что является ожидаемым компромиссом. +\begin{itemize} + \item Версия без JIT: ускорение 0.70--0.74x (замедление примерно на 36--42\%). + \item Версия с JIT: ускорение 0.96--0.99x (замедление примерно на 1--4\%). +\end{itemize} + +Применение JIT-компиляции позволило существенно сократить разрыв со стандартной реализацией, в абсолютных значениях времени версия с JIT работает значительно быстрее версии без JIT (рис.~\ref{fig:v3}). + +Увеличение времени относительно стандартной реализации обусловлено необходимостью двух проходов по данным вместо одного. + +\begin{figure}[H] + \centering + \includegraphics[width=0.9\textwidth]{images/time_comparison.pdf} + \caption{Сравнение времени выполнения: JIT vs Generic} + \label{fig:v3} +\end{figure} + +\subsection{Выводы из экспериментов} +Предложенная оптимизация успешно решает поставленную задачу снижения пикового потребления памяти, что особенно важно для анализа больших графов программ. Увеличение времени выполнения является приемлемым компромиссом, так как во многих сценариях статического анализа ограничение по памяти является более критичным фактором, чем время выполнения. + +\section{Заключение} + +В ходе выполнения работы получены следующие результаты. + +\begin{itemize} + \item Добавлена фильтрация нулевых элементов на этапе вычисления в алгоритм произведения Кронекера для разреженных матриц в SuiteSparse:GraphBLAS. + \item Реализован двухпроходный алгоритм с предварительным подсчётом ненулевых элементов и выделением памяти только под значащие элементы результата. + \item Достигнуто снижение пикового потребления памяти произведением Кронекера в 2.1--2.4 раза на различных наборах данных из области статического анализа кода. + \item Алгоритм адаптирован к актуальной версии библиотеки SuiteSparse:GraphBLAS. + \item Проведённое экспериментальное исследование подтвердило эффективность оптимизации по памяти при приемлемом увеличении времени выполнения. +\end{itemize} + +Решение не является финальным и открывает направления для дальнейшей работы: +\begin{itemize} + \item дальнейшая оптимизация производительности с целью сведения временных затрат к уровню стандартной реализации библиотеки; + \item добавление возможности отбирать ненулевые элементы по пользовательскому критерию вместо использующейся сейчас побайтовой проверки на 0. +\end{itemize} + +Pull Request: \url{https://github.com/kijexs/GraphBLAS/pull/3} + +\begin{thebibliography}{9} +\bibitem{orachev2020} +Orachev, E., Epelbaum, I., Azimov, R., Grigorev, S. (2020). Context-Free Path Querying by Kronecker Product. In: Darmont, J., Novikov, B., Wrembel, R. (eds) Advances in Databases and Information Systems. ADBIS 2020. Lecture Notes in Computer Science, vol 12245. Springer, Cham. https://doi.org/10.1007/978-3-030-54832-2\_6 + +\bibitem{graphblas} +Исходный код библиотеки SuiteSparse:GraphBLAS [Электронный ресурс]. URL: \url{https://github.com/SparseLinearAlgebra/GraphBLAS}. + +\bibitem{kutuev2023} +Experimental investigation of context-free-language reachability algorithms as applied to static code analysis / Kutuev Vladimir. URL: \url{https://dspace.spbu.ru/items/36014e9c-fae5-4793-9f17-7c1ddfc3421c}. +\end{thebibliography} + +\end{document} diff --git a/Ella_Zamyatina/Ella_Zamyatina_report.tex b/Ella_Zamyatina/Ella_Zamyatina_report.tex new file mode 100644 index 0000000..9358fcf --- /dev/null +++ b/Ella_Zamyatina/Ella_Zamyatina_report.tex @@ -0,0 +1,164 @@ +\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{enumitem} +\usepackage{amsmath} +\usepackage{graphicx} + +\title{Реализация свёртки изображений на Python} + +\author{Замятина Элла Андреевна} + +\date{} + +\begin{document} + +\maketitle + +\begin{flushright} + Группа: \emph{\enquote{25.Б43-мм}} + + Кафедра: \emph{системного программирования} + + Научный руководитель: \emph{Пономарев Николай Алексеевич} + + Номер семестра практики: \emph{2} +\end{flushright} + +\section{Введение} + +Свёртка~--- одна из базовых операций в обработке изображений. Она применяется для размытия, повышения резкости, выделения границ и других преобразований. Двумерная свёртка изображения $I$ с ядром $K$ размера $k \times k$ определяется как сумма поэлементных произведений пикселей окна и коэффициентов ядра: +\[ +(I * K)[i, j] = \sum_{u=0}^{k-1} \sum_{v=0}^{k-1} I_{\text{pad}}[i+u,\, j+v] \cdot K[u, v], +\] +где $I_{\text{pad}}$~--- изображение после дополнения границ. В работе реализована данная операция на языке Python, проведено тестирование и сравнение производительности с OpenCV и Pillow. + +\section{Постановка задачи} + +\textbf{Цель работы:} реализовать операцию двумерной свёртки изображений, провести тестирование и сравнить производительность с библиотечными аналогами. + +\textbf{Задачи:} +\begin{itemize} + \item Реализовать функцию свёртки, работающую как с RGB-изображениями, так и с полутоновыми изображениями. + \item Реализовать четыре режима дополнения границ: \verb|zero|, \verb|edge|, \verb|reflect|, \verb|wrap|. + \item Подготовить набор из восьми ядер размером $3 \times 3$ и $5 \times 5$. + \item Написать интеграционные тесты с эталонными изображениями. + \item Провести сравнительный анализ производительности собственной реализации с OpenCV и Pillow. +\end{itemize} + +\section{Реализация} + +Проект представляет собой консольное приложение на языке Python. Выбор данного формата обусловлен учебным характером работы: основное внимание уделяется реализации алгоритма свёртки, а не разработке графического интерфейса. При этом сам алгоритм вынесен в отдельный модуль \verb|convolution.py|, который может использоваться как библиотечная функция независимо от интерфейса командной строки. Взаимодействие с пользователем, загрузка и сохранение изображений реализованы в модуле \verb|main.py|. Остальные модули отвечают за отдельные аспекты: \verb|padding.py|~--- дополнение границ, \verb|kernels.py|~--- ядра фильтров, \verb|benchmark.py|~--- визуализация результатов измерений. + +\subsection{Загрузка и подготовка изображения} + +Изображение загружается с помощью библиотеки Pillow. При наличии флага \verb|--gray| выполняется перевод в полутоновое изображение через встроенный метод \verb|Image.convert("L")|. +\subsection{Режимы дополнения (padding)} + +Поскольку применение ядра к граничным пикселям требует данных за пределами изображения, в модуле \verb|padding.py| реализована функция \verb|apply_padding|, которая дополняет изображение с помощью \verb|np.pad|. Доступны четыре режима: + +\begin{itemize} + \item \textbf{zero}~--- заполнение нулями (\verb|mode="constant"|). + \item \textbf{edge}~--- копирование крайних пикселей (\verb|mode="edge"|). + \item \textbf{reflect}~--- зеркальное отражение без дублирования границы (\verb|mode="reflect"|). + \item \textbf{wrap}~--- циклическое продолжение (\verb|mode="wrap"|). +\end{itemize} + +Размер дополнения вычисляется как половина размера ядра: для ядра $3 \times 3$ добавляется по одному пикселю с каждой стороны, для $5 \times 5$~--- по два. + +\subsection{Функция свёртки} + +Основная функция \verb|apply_convolution| из модуля \verb|convolution.py| принимает изображение в виде массива NumPy, ядро свёртки и режим дополнения. Алгоритм работает следующим образом: + +\begin{enumerate} + \item Если изображение двумерное (полутоновое), оно приводится к трёхмерному виду добавлением оси канала. + \item Вызывается \verb|apply_padding| для формирования дополненного массива. + \item Функция \verb|sliding_window_view| из NumPy формирует пятимерный массив, где каждый пространственный пиксель содержит окно размера ядра. + \item Свёртка вычисляется с помощью функции \verb|np.einsum| и опции \verb|optimize="greedy"|. + \item Результат ограничивается диапазоном $[0, 255]$ и приводится к типу \verb|uint8|. +\end{enumerate} + +В процессе разработки проводилась оптимизация. Начальная версия с тремя вложенными циклами по высоте, ширине и элементам ядра демонстрировала время выполнения около 2200~мс для RGB-изображения $1024 \times 1024$ с ядром $3 \times 3$. Замена внутреннего цикла на \verb|sliding_window_view| с последующим \verb|np.sum| позволила сократить время до приблизительно 110~мс. Итоговая версия с \verb|np.einsum| и \verb|optimize="greedy"| выполняет свёртку за примерно 6~мс. Суммарное ускорение составило более 350 раз. + +\subsection{Ядра фильтров} + +В словаре \verb|KERNELS| модуля \verb|kernels.py| определены 8 ядер. Для каждого типа доступны версии $3 \times 3$ и $5 \times 5$: + +\begin{itemize} + \item \textbf{identity\_kernel}~--- единичное ядро, не изменяет изображение. + \item \textbf{box\_blur}~--- равномерное усредняющее ядро (box blur). + \item \textbf{gaussian}~--- гауссово размытие. + \item \textbf{sharpen}~--- повышение резкости. +\end{itemize} + +Ядра загружаются функцией \verb|get_kernel| по строковому имени. + +\subsection{Интерфейс командной строки} + +Точка входа в \verb|main.py| использует \verb|argparse|. Поддерживаются аргументы: +\begin{itemize} + \item \verb|input|, \verb|output|~--- пути ко входному и выходному изображению. + \item \verb|--kernel|~--- выбор ядра (по умолчанию \verb|blur|). + \item \verb|--padding|~--- режим дополнения (по умолчанию \verb|zero|). + \item \verb|--gray|~--- флаг перевода в полутоновое изображение. +\end{itemize} + +\section{Тестирование} + +Для проверки корректности реализованы интеграционные тесты в файле \verb|tests/test_integration.py| с использованием эталонных изображений. Для каждой комбинации ядра и режима дополнения эталонное изображение было заранее получено с помощью библиотеки OpenCV (\verb|cv2.filter2D|) и сохранено в директории \verb|tests/golden/| в формате PNG. При запуске теста функция \verb|apply_convolution| применяет свёртку к входному изображению, после чего результат поэлементно сравнивается с эталоном с помощью \verb|np.array_equal|, что гарантирует точное совпадение. + +\section{Экспериментальное исследование производительности} + +Эксперименты проводились на системе со следующими характеристиками: +\textit{процессор} Intel Core i5-5200U, \textit{ОЗУ} 16~ГБ, \textit{ОС} EndeavourOS Linux. + +Для измерений использовалась библиотека \verb|pytest-benchmark| (файл \verb|tests/test_benchmark.py|). Сравнивались три реализации: +\begin{itemize} + \item \textbf{custom}~--- собственная функция \verb|apply_convolution|. + \item \textbf{opencv}~--- \verb|cv2.filter2D|. + \item \textbf{pillow}~--- \verb|ImageFilter.Kernel|. +\end{itemize} + +Измерения проводились на случайных изображениях размеров $1024 \times 1024$ и $2048 \times 2048$ пикселей в двух цветовых режимах (RGB и полутоновом) для всех 8 ядер. Измерения запускались через pytest с библиотекой \verb|pytest-benchmark|, результаты визуализированы скриптом \verb|benchmark.py| и представлены на рисунке~\ref{fig:bench}. + +\begin{figure}[ht] + \centering + \includegraphics[width=0.825\textwidth]{benchmark.pdf} + \caption{Сравнение времени выполнения свёртки для трёх реализаций. Ось Y~--- логарифмическая. Планки погрешностей соответствуют стандартному отклонению по 5 запускам.} + \label{fig:bench} +\end{figure} + +OpenCV является наиболее быстрой реализацией для всех конфигураций благодаря низкоуровневым оптимизациям на C++ и SIMD-инструкциям. Pillow показывает промежуточные результаты. Собственная реализация уступает библиотечным, однако после применения \verb|np.einsum| время выполнения существенно сократилось по сравнению с исходной версией. Размер ядра влияет на производительность: для ядер $5 \times 5$ время выполнения в 2--5 раз больше, чем для $3 \times 3$. Обработка полутоновых изображений выполняется быстрее RGB пропорционально числу каналов. + +\section{Заключение} + +В ходе выполнения работы получены следующие результаты: +\begin{itemize} + \item Написаны интеграционные тесты на основе эталонных изображений, подтверждающие корректность реализации. + \item Проведено сравнение производительности с OpenCV и Pillow, показавшее ожидаемое преимущество библиотечных реализаций. +\end{itemize} + +Репозиторий с реализацией: \url{https://github.com/ellazamyatina/image_convolution_practice} + +\end{document} diff --git a/Matvey_Timofeev/Matvey_Timofeev_report.tex b/Matvey_Timofeev/Matvey_Timofeev_report.tex new file mode 100644 index 0000000..93e2f90 --- /dev/null +++ b/Matvey_Timofeev/Matvey_Timofeev_report.tex @@ -0,0 +1,173 @@ +\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{enumitem} +\usepackage{graphicx} +\usepackage{float} +% Для корректных ссылок на изображения с помощью \ref{...} +\usepackage{caption} +\captionsetup{hypcap=true} + +\title{LamaGraph: знакомство с HDL} + +\author{Тимофеев Матвей Игоревич} + +% Дата много места занимает, её лучше не указывать. +\date{} + +\begin{document} + +\maketitle + +\begin{flushright} + Группа: \emph{\enquote{25.Б71-мм}} + + Кафедра: \emph{системного программирования} + + Научный руководитель: \emph{кандидат физико-математических наук, доцент кафедры системного программирования Григорьев Семён Вячеславович} + + Номер семестра практики: \emph{2} +\end{flushright} + +\section{Введение} + +HDL~--- это языки описания аппаратуры. Такие языки используются для программирования ПЛИС, а также для описания и отладки внутренней логики процессоров. Одним из таких языков является SystemVerilog. + +В контексте учебной практики предлагается освоить SystemVerilog на базовом уровне. В дальнейшем это позволит принимать участие в реальных проектах, где требуются знания данного языка и связанных с ним понятий, например, в проекте LamaGraph\footnote{LamaGraph~--- проект по разработке специализированного вычислителя для разреженной линейной алгебры и специализированного языка программирования для него. Репозиторий проекта: \url{https://github.com/Lamagraph/interaction-nets-in-fpga} (дата обращения: 30.04.2026)}. + +\section{Постановка задачи} + +\textbf{Целью работы является} получение базовых навыков разработки на SystemVerilog. Для этого предлагается решить все задачи из второго, третьего и четвёртого блоков открытого курса по FPGA и Clash\footnote{Курс по FPGA и Clash был создан на математико-механическом факультете СПбГУ. Он содержит обучающие материалы по разработке на языках SystemVerilog и Clash. Страница курса находится по адресу: \url{https://lamagraph.github.io/intro-to-fpga-with-clash/index.html} (дата обращения: 30.04.2026)}, каждый блок которого состоит из теории и самих задач, которые подразумевают написание различных модулей на языке SystemVerilog. + +\textbf{Суть задач.} +\begin{itemize} [leftmargin=3.5em, topsep=0pt] + \item Блок 2: задачи направлены на обучение написанию простейших модулей и тестов к ним. + + \item Блок 3: задачи требуют реализовать различные модули, которые используют в себе другие модули. + + \item Блок 4: задачи ориентированы на работу с мультиплексорами. +\end{itemize} + +\section{Описание предлагаемого решения} + +\subsection{Блок 2:} + +В данном блоке требовалось написать 4 модуля для четырёх логических операций соответственно: импликации, отрицания импликации, стрелки Пирса (отрицание ИЛИ) и штриха Шеффера (отрицание И). Для реализации всех модулей были использованы встроенные в язык стандартные побитовые логические операции: ИЛИ, И, НЕ. Также для всех модулей было необходимо написать тесты. Тесты используют таблицы истинности соответствующих логических операций для проверки корректности работы модулей. + +\subsection{Блок 3:} + +\begin{itemize} + \item Первое задание в данном блоке требовало написать модули для конъюнкции, дизъюнкции и импликации, используя только стрелку Пирсa. Второе требовало выразить эти же операции только через штрих Шеффера. Реализации штриха Шеффера и стрелки Пирса были взяты из заданий блока 2. Также для этих модулей были написаны тесты, так как это требовалось в задаче 3 данного блока. + + \item В четвёртом задании было необходимо реализовать сумматор для k n-битных чисел, переиспользуя данный изначально модуль \verb|adder_multibits_reuse|, который умеет выполнять сложение двух чисел произвольной разрядности. Требуемый в задании модуль был реализован при помощи каскадного подключения модулей \verb|adder_multibits_reuse|, так что для k чисел сначала складывалось первое число со вторым, после результат с третьим числом, полученный с предыдущего шага результат с четвёртым и т.д. Было выбрано каскадное подключение модулей, а не параллельное в силу более простой и понятной его реализации. + + Также стоит сказать, что реализация сумматора для k n-битных чисел~--- это модуль, который при создании параметризуется разрядностью чисел и их количеством. То есть для каждой уникальной пары (количество чисел, разрядность чисел) экземпляры созданных модулей будут различаться. Количество чисел используется для определения количества модулей \verb|adder_multibits_reuse|, которые должен содержать основной модуль. Разрядность чисел же используется для вычисления максимальной разрядности, которую может иметь сумма на выходе. + + Рассмотрим подробнее устройство данного модуля на примере его экземпляра, складывающего четыре 8-битных числа. Он имеет логическую схему, представленную на рисунке~\ref{fig:adder_k_numbers}. + \begin{figure}[H] + \centering + \includegraphics{images/adder_k_numbers.pdf} + \caption{Сумматор для четырёх 8-битных чисел} + \label{fig:adder_k_numbers} + \end{figure} + + На вход модуля подаётся массив из чисел, которые необходимо сложить. Вначале вычисляется максимальная разрядность результата суммы, которая в данном случае равна 10 битам. Следовательно, все модули \verb|adder_multibits_reuse| параметризуются этой разрядностью и все 8-битные числа, которые подаются на входы $a$ и $b$ этих модулей, дополняются слева двумя нулевыми битами, так как модуль \verb|adder_multibits_reuse| работает с числами одинаковой разрядности. Также, так как известна итоговая максимальная разрядность, то переполнения при сложении двух чисел не будет. Поэтому входы $c\_in$, отвечающие за входной бит переполнения, и выходы $c\_out$, отвечающие за выходной бит переполнения, модулей \verb|adder_multibits_reuse| не используются. Поэтому на все $c\_in$ подаётся бит $0$, а провода из $c\_out$ ни к чему не подсоединены. + + \item В пятом задании нужно было реализовать сумматор k чисел типа int. Это задание было выполнено аналогично четвёртому: с помощью каскадного подключения модулей, складывающих два числа типа int. Модуль, складывающий два числа типа int, был написан дополнительно. + + \item Шестое задание требовало создать модуль для свёртки битвектора фиксированного, но параметризуемого размера для любой логической операции. Модуль был реализован для логического ИЛИ с помощью каскадного подключения вентилей ИЛИ. В качестве логической операции операция ИЛИ была выбрана случайно, так как реализация модулей для других логических операций отличалась бы незначительно. + + \item Седьмое задание заключалось в реализации модуля из шестого задания, но для одной из операций, реализованных в заданиях 1 и 2. В решении использовалось каскадное подключение модулей, реализующих дизъюнкцию. Таким образом, написанный в седьмом задании модуль для свёртки битвектора может в качесте модуля дизъюнкции использовать любой модуль с подходящей реализацией и названием, в том числе и модули дизъюнкции написанные в первом и втором заданиях. +\end{itemize} + +\subsection{Блок 4:} + +\begin{itemize} + \item Первое задание в данном блоке требовало реализовать мультиплексор 4:1 через логические операторы И, ИЛИ, НЕ. Сначала в качестве решения был написан модуль, который от каждого входного бита в зависимости от значения селектора берёт либо 0, либо значение этого бита, а в конце все полученные биты скрещивает оператором ИЛИ. + + Например, пусть селектор равен $\overline{ab}$, где $a, b$~--- биты, а первый входной бит равен $in_0$. Тогда, скрестив $in_0$ оператором И с НЕ($a$ ИЛИ $b$), мы получим $in_0$ тогда и только тогда, когда $a = 0$ и $b = 0$, то есть селектор равен $00$, а в остальных случаях получится $0$. Тогда, если второй, третий и четвёртый входной биты равны соответственно $in_1, in_2$ и $in_3$, итоговой формулой для результата будет: + $$ + (in_0 \land \lnot(a \lor b)) \lor (in_1 \land \lnot(a) \land b) \lor (in_2 \land a \land \lnot(b)) \lor (in_3 \land a \land b) + $$ + В этой формуле три скобки всегда будут нулевые, а оставшаяся будет содержать значение выбранного селектором бита. + + Сгенерированная логическая схема модуля представлена на рисунке~\ref{fig:mux_4to1_logic}. + \begin{figure}[H] + \centering + \includegraphics{images/mux_4to1_logic.pdf} + \caption{Мультиплексор 4:1~--- первый вариант схемы} + \label{fig:mux_4to1_logic} + \end{figure} + + Как видно, данная реализация модуля требует 14 логических вентилей, что довольно избыточно. Поэтому был реализован ещё один мультиплексор 4:1, который сначала параллельно выбирает один бит из двух младших входных бит и один бит из двух старших входных бит, а потом из них выбирает результирующий бит. Алгоритм выбора такой: если младший бит селектора равен 0, то результирующим битом будет либо первый входной бит, либо третий, поэтому из двух младших входных бит и двух старших входных бит выбираем соответственно первый и третий входные биты. Если же младший бит селектора равен 1, то берём второй и четвёртый биты. После, если старший бит селектора равен 0, то на выходе должен быть либо первый, либо второй входной бит, поэтому выбираем бит, выбранный ранее из двух младших входных бит. Если же старший бит селектора равен 1, то выбираем бит, выбранный ранее из двух старших входных бит. Такой модуль уже требует 11 логических вентилей вместо 14 и имеет логическую схему, представленную на рисунке~\ref{fig:mux_4to1_logic_optimized}. + \begin{figure}[H] + \centering + \includegraphics{images/mux_4to1_logic_optimized.pdf} + \caption{Оптимизированная версия мультиплексора 4:1} + \label{fig:mux_4to1_logic_optimized} + \end{figure} + + Также для мультиплексора 4:1 был написан тест. + + \item Во втором задании было необходимо реализовать импликацию через мультиплексор 2:1. Решение использует один данный мультиплексор, который при входных битах a и b выбирает b при a = 1, иначе 1. + + \item Третье задание требовало реализации Look-Up Table для стрелки Пирса. В решении использовался один мультиплексор 4:1, который в качестве селектора принимает сконкатенированные входные биты, а в качестве последовательности битов для выбора всегда принимает 0001 (последний бит~--- самый младший). Тогда этот мультиплексор будет возвращать 1 тогда и только тогда, когда оба входных бита нулевые, поэтому он служит таблицей истинности для стрелки Пирса. Логическая схема модуля представлена на рисунке~\ref{fig:lut_peirce_arrow}. + \begin{figure}[H] + \centering + \includegraphics{images/lut_peirce_arrow.pdf} + \caption{Look-Up Table для стрелки Пирса} + \label{fig:lut_peirce_arrow} + \end{figure} + +\item В четвёртом задании было необходимо написать модуль, использующий только мультиплексоры 2:1, который принимает биты a, b, c и возвращает результат трёхместного отношения \lnot(a \lor\ b) \land\ c. Для того чтобы для решения задачи было достаточно двух мультиплексоров 2:1, исходное отношение было преобразовано в \lnot b \land\ (\lnot a \land\ c). Теперь достаточно посчитать два выражения вида \lnot x \land\ y, которые можно вычислить одним мультиплексором 2:1 так: если x = 0, то выбираем y, иначе 0. Таким образом, имеем схему модуля, представленную на рисунке~\ref{fig:solution}. + \begin{figure}[H] + \centering + \includegraphics{images/solution.pdf} + \caption{Модуль, вычисляющий \lnot(a \lor\ b) \land\ c} + \label{fig:solution} + \end{figure} +\end{itemize} + +При выполнении заданий для исполнения программ на языке SystemVerilog использовался симулятор Icarus Verilog. Для генерации схем из модулей использовались утилиты Yosys и netlistsvg. + +\section{Тестирование} + +Все написанные тесты, кроме теста для первого задания 4 блока, проверяют корректность модулей с помощью заранее известных таблиц истинности. Для каждого блока создан отдельный скрипт \verb|build_and_test_all.sh|, при запуске которого исполняются тесты для всех заданий данного блока, для которых эти тесты есть. Также для тестов настроено CI на github. + +\section{Заключение} + +В ходе выполнения работы получены следующие результаты. + +\begin{itemize} + \item Решены все задачи из второго блока курса, что позволило научиться написанию простейших модулей и тестов к ним на языке SystemVerilog. + \item Решены все задачи из третьего блока курса, благодаря чему получен навык написания немного более сложных модулей. + \item Решены все задачи из четвёртого блока курса, что позволило обучиться работе с мультиплексорами. + \item Кроме того, в процессе выполнения работы в курсе было обнаружено несколько опечаток, которые были исправлены\footnote{Ссылки на принятые в репозиторий курса запросы на изменения, содержащие исправления опечаток: \url{https://github.com/Lamagraph/intro-to-fpga-with-clash/pull/66} (дата обращения: 08.05.2026); \url{https://github.com/Lamagraph/intro-to-fpga-with-clash/pull/72} (дата обращения: 08.05.2026)}. +\end{itemize} + +Таким образом, были получены базовые навыки разработки на языке SystemVerilog, что и являлось целью учебной практики. + +Репозиторий с решениями задач: \url{https://github.com/meow79/FPGA\_learning} + +\end{document} diff --git a/Nikita_Brulevich/Nikita_Brulevich_report.tex b/Nikita_Brulevich/Nikita_Brulevich_report.tex index 2e41eff..8ce055d 100644 --- a/Nikita_Brulevich/Nikita_Brulevich_report.tex +++ b/Nikita_Brulevich/Nikita_Brulevich_report.tex @@ -75,7 +75,7 @@ \section{Обзор} Основная идея библиотеки QTreeFSharp заключается в использовании деревьев квадрантов для представления разреженных матриц. -В отличие от традиционных форматов (CSR, COO), деревья квадрантов позволяют эффективно выполнять рекурсивные операции за счёт логарифмической сложности доступа и возможности схлопывания одинаковых значений в один лист (UserValue(v)). Данная структура хорошо согласуется с функциональной парадигмой языка F\# и обеспечивает неизменяемость данных. +В отличие от традиционных форматов (CSR, COO), деревья квадрантов позволяют эффективно выполнять рекурсивные операции за счёт логарифмической сложности доступа и возможности схлопывания одинаковых значений в один лист (UserValue(v)). \subsection{Исследовательские вопросы} @@ -89,13 +89,9 @@ \subsection{Исследовательские вопросы} \section{Описание предлагаемого решения} -\subsection{Структуры данных} +В проекте QTreeFSharp уже была реализована основа для работы с разреженными матрицами и векторами. Разреженные векторы представлены бинарным деревом (\texttt{btree}), где листья содержат \texttt{UserValue} или \texttt{Dummy}. Размер дерева округляется до ближайшей степени двойки. Разреженные матрицы реализованы на дереве квадрантов (\texttt{qtree}) с четырьмя подузлами (NW, NE, SW, SE), что позволяет рекурсивно делить матрицу на квадранты. -Разреженные векторы реализованы на бинарном дереве (\texttt{btree}), где листья содержат \texttt{UserValue} или \texttt{Dummy}. Размер дерева округляется до ближайшей степени двойки. - -Разреженные матрицы реализованы на дереве квадрантов (\texttt{qtree}) с четырьмя подузлами (NW, NE, SW, SE), что позволяет рекурсивно делить матрицу на квадранты. - -\subsection{Реализованные операции} +В рамках расширения библиотеки были реализованы и оптимизированы следующие операции: \begin{itemize} \item \texttt{reduceRows}, \texttt{reduceCols}~--- свёртка матрицы в вектор с использованием заданной бинарной операции по строкам и по столбцам соответственно @@ -112,8 +108,7 @@ \subsection{Реализованные операции} \item Транспонирование матрицы с последующей свёрткой по строкам (альтернативный подход с учётом уже реализованной в проекте функции transpose). \end{enumerate} -\subsection{Тестирование} - +\textbf{Тестирование.} Для каждой из новых реализованных функций написаны Unit-тесты: \begin{itemize} \item \texttt{Vector.slice}~--- 11 тестов @@ -123,7 +118,7 @@ \subsection{Тестирование} \item \texttt{Matrix.reduceCols}~--- 7 тестов \item \texttt{Matrix.kroneckerProduct}~--- 13 тестов \end{itemize} -А также добавлены отсутствующие тесты на уже имевшиеся функции --- 17 тестов. +Кроме того, добавлены отсутствующие тесты на уже имевшиеся функции --- 17 тестов. \section{Эксперименты} @@ -140,7 +135,7 @@ \subsection{Методология} \subsection{Результаты} -\subsubsection{ReduceRows и ReduceCols} +\textbf{ReduceRows и ReduceCols} Результаты замеров производительности операций редукции приведены в табл.~\ref{tab:reduce}. @@ -154,35 +149,38 @@ \subsubsection{ReduceRows и ReduceCols} \midrule \multicolumn{4}{c}{\textbf{Sparse (разреженные, случайные)}} \\ \midrule -ReduceRows\_SparseSmall & 32×32 & 64.2 μs & 67.6 KB \\ -ReduceCols\_SparseSmall & 32×32 & 65.7 μs & 72.7 KB \\ -ReduceRows\_SparseMedium & 256×256 & 1.73 ms & 1.27 MB \\ -ReduceCols\_SparseMedium & 256×256 & 1.87 ms & 1.35 MB \\ -ReduceRows\_SparseLarge & 1024×1024 & 9.31 ms & 4.59 MB \\ -ReduceCols\_SparseLarge & 1024×1024 & 10.16 ms & 4.97 MB \\ +ReduceRows\_SparseSmall & 32$\times$32 & 64.2 μs & 67.6 KB \\ +ReduceCols\_SparseSmall & 32$\times$32 & 65.7 μs & 72.7 KB \\ +ReduceRows\_SparseMedium & 256$\times$256 & 1.73 ms & 1.27 MB \\ +ReduceCols\_SparseMedium & 256$\times$256 & 1.87 ms & 1.35 MB \\ +ReduceRows\_SparseLarge & 1024$\times$1024 & 9.31 ms & 4.59 MB \\ +ReduceCols\_SparseLarge & 1024$\times$1024 & 10.16 ms & 4.97 MB \\ \midrule \multicolumn{4}{c}{\textbf{DenseUniform (плотные, все 1.0)}} \\ \midrule -ReduceRows\_DenseUniformSmall & 32×32 & 255.6 μs & 308 KB \\ -ReduceCols\_DenseUniformSmall & 32×32 & 264.5 μs & 313 KB \\ -ReduceRows\_DenseUniformMedium & 256×256 & 56.7 ms & 17.6 MB \\ -ReduceCols\_DenseUniformMedium & 256×256 & 72.4 ms & 17.6 MB \\ -ReduceRows\_DenseUniformLarge & 1024×1024 & 856 ms & 276 MB \\ -ReduceCols\_DenseUniformLarge & 1024×1024 & 1137 ms & 277 MB \\ +ReduceRows\_DenseUniformSmall & 32$\times$32 & 255.6 μs & 308 KB \\ +ReduceCols\_DenseUniformSmall & 32$\times$32 & 264.5 μs & 313 KB \\ +ReduceRows\_DenseUniformMedium & 256$\times$256 & 56.7 ms & 17.6 MB \\ +ReduceCols\_DenseUniformMedium & 256$\times$256 & 72.4 ms & 17.6 MB \\ +ReduceRows\_DenseUniformLarge & 1024$\times$1024 & 856 ms & 276 MB \\ +ReduceCols\_DenseUniformLarge & 1024$\times$1024 & 1137 ms & 277 MB \\ \midrule \multicolumn{4}{c}{\textbf{DenseRandom (плотные, случайные)}} \\ \midrule -ReduceRows\_DenseRandomSmall & 32×32 & 277.6 μs & 308 KB \\ -ReduceCols\_DenseRandomSmall & 32×32 & 293.2 μs & 312 KB \\ -ReduceRows\_DenseRandomMedium & 256×256 & 77.9 ms & 17.6 MB \\ -ReduceCols\_DenseRandomMedium & 256×256 & 74.6 ms & 17.6 MB \\ -ReduceRows\_DenseRandomLarge & 1024×1024 & 1072 ms & 276 MB \\ -ReduceCols\_DenseRandomLarge & 1024×1024 & 1106 ms & 277 MB \\ +ReduceRows\_DenseRandomSmall & 32$\times$32 & 277.6 μs & 308 KB \\ +ReduceCols\_DenseRandomSmall & 32$\times$32 & 293.2 μs & 312 KB \\ +ReduceRows\_DenseRandomMedium & 256$\times$256 & 77.9 ms & 17.6 MB \\ +ReduceCols\_DenseRandomMedium & 256$\times$256 & 74.6 ms & 17.6 MB \\ +ReduceRows\_DenseRandomLarge & 1024$\times$1024 & 1072 ms & 276 MB \\ +ReduceCols\_DenseRandomLarge & 1024$\times$1024 & 1106 ms & 277 MB \\ \bottomrule \end{tabular} \end{table} -\subsubsection{Сравнение reduceCols и reduceCols как transpose + reduceRows} +Разреженные матрицы демонстрируют преимущество над плотными во всех размерах. На малых матрицах (32$\times$32) выигрыш составляет 3-4 раза (64-66 μs против 256-293 μs), на средних (256$\times$256)~--- 30-40 раз (1.7-1.9 ms против 56-78 ms), на больших (1024$\times$1024)~--- до 120 раз (9-10 ms против 856-1137 ms). Аллокации памяти также отличаются в 4, 15 и 60 раз соответственно. Результаты времени выполнения для плотных матриц с единичными и случайными значениями (DenseUniform и DenseRandom) близки, разница не превышает 25\%, разница объёма аллоцированной памяти~--- не более 2\%. + + +\textbf{Сравнение reduceCols и reduceCols как transpose + reduceRows} Сравнение производительности двух реализаций приведено в табл.~\ref{tab:reducecols}. @@ -198,18 +196,18 @@ \subsubsection{Сравнение reduceCols и reduceCols как transpose + re \cline{3-6} & & Оригинал & Транспонирование & Оригинал & Транспонирование & \\ \midrule -ReduceCols\_SparseSmall & 32×32 & 66.5 μs & 78.5 μs & 72.7 KB & 75.0 KB & +18\% \\ -ReduceCols\_DenseSmall & 32×32 & 265 μs & 261 μs & 313 KB & 310 KB & -1.5\% \\ -ReduceCols\_SparseMedium & 256×256 & 1.84 ms & 2.78 ms & 1.35 MB & 1.40 MB & +51\% \\ -ReduceCols\_DenseMedium & 256×256 & 64.8 ms & 57.5 ms & 17.6 MB & 17.6 MB & \textbf{-11\%} \\ -ReduceCols\_SparseLarge & 1024×1024 & 9.89 ms & 19.5 ms & 4.97 MB & 5.10 MB & +97\% \\ -ReduceCols\_DenseLarge & 1024×1024 & 1.14 s & 0.89 s & 277 MB & 277 MB & \textbf{-22\%} \\ +ReduceCols\_SparseSmall & 32$\times$32 & 66.5 μs & 78.5 μs & 72.7 KB & 75.0 KB & +18\% \\ +ReduceCols\_DenseSmall & 32$\times$32 & 265 μs & 261 μs & 313 KB & 310 KB & -1.5\% \\ +ReduceCols\_SparseMedium & 256$\times$256 & 1.84 ms & 2.78 ms & 1.35 MB & 1.40 MB & +51\% \\ +ReduceCols\_DenseMedium & 256$\times$256 & 64.8 ms & 57.5 ms & 17.6 MB & 17.6 MB & \textbf{-11\%} \\ +ReduceCols\_SparseLarge & 1024$\times$1024 & 9.89 ms & 19.5 ms & 4.97 MB & 5.10 MB & +97\% \\ +ReduceCols\_DenseLarge & 1024$\times$1024 & 1.14 s & 0.89 s & 277 MB & 277 MB & \textbf{-22\%} \\ \bottomrule \end{tabular} } \end{table} -На рис.~\ref{fig:reducecols_time} представлено сравнение времени выполнения, а на рис.~\ref{fig:reducecols_memory} — сравнение аллокаций памяти. +На рис.~\ref{fig:reducecols_time} представлено сравнение времени выполнения, а на рис.~\ref{fig:reducecols_memory} ~--- сравнение аллокаций памяти. \begin{figure}[H] \centering @@ -225,9 +223,9 @@ \subsubsection{Сравнение reduceCols и reduceCols как transpose + re \label{fig:reducecols_memory} \end{figure} -На плотных матрицах реализация через транспонирование оказывается быстрее на 10-22\% благодаря лучшей кэш-локальности. На разреженных матрицах, напротив, прямой обход по столбцам оказывается быстрее на 18-97\%. +Вывод из сравнения реализаций reduceCols: транспонирование эффективнее на плотных матрицах (ускорение растёт с размером: 1.5\%, 11\%, 22\%), но проигрывает на разреженных (замедление 18\%, 51\%, 97\%). Это объясняется лучшей кэш-локальностью при последовательном обходе строк после транспонирования. -\subsubsection{Slice для векторов} +\textbf{Slice для векторов} \begin{table}[H] \centering @@ -246,7 +244,7 @@ \subsubsection{Slice для векторов} \end{tabular} \end{table} -\subsubsection{Slice для матриц} +\textbf{Slice для матриц} \begin{table}[H] \centering @@ -255,17 +253,19 @@ \subsubsection{Slice для матриц} \toprule Метод & Размер & Время (Mean) & Аллокации \\ \midrule -MatrixSlice\_SparseSmall & 32×32 & 68.8 μs & 68 KB \\ -MatrixSlice\_DenseSmall & 32×32 & 53.3 μs & 77 KB \\ -MatrixSlice\_SparseMedium & 256×256 & 14.0 ms & 6.9 MB \\ -MatrixSlice\_DenseMedium & 256×256 & 15.0 ms & 7.2 MB \\ -MatrixSlice\_SparseLarge & 1024×1024 & 285 ms & 138 MB \\ -MatrixSlice\_DenseLarge & 1024×1024 & 302 ms & 139 MB \\ +MatrixSlice\_SparseSmall & 32$\times$32 & 68.8 μs & 68 KB \\ +MatrixSlice\_DenseSmall & 32$\times$32 & 53.3 μs & 77 KB \\ +MatrixSlice\_SparseMedium & 256$\times$256 & 14.0 ms & 6.9 MB \\ +MatrixSlice\_DenseMedium & 256$\times$256 & 15.0 ms & 7.2 MB \\ +MatrixSlice\_SparseLarge & 1024$\times$1024 & 285 ms & 138 MB \\ +MatrixSlice\_DenseLarge & 1024$\times$1024 & 302 ms & 139 MB \\ \bottomrule \end{tabular} \end{table} -\subsubsection{Произведение Кронекера} +На всех размерах производительность среза (slice) для разреженных и плотных матриц/векторов остаётся сопоставимой (разница не превышает 10-15\%). + +\textbf{Произведение Кронекера} \begin{table}[H] \centering @@ -274,34 +274,22 @@ \subsubsection{Произведение Кронекера} \toprule Метод & Исходный размер & Время (Mean) & Аллокации \\ \midrule -Kronecker\_SparseSmall & 8×8 & 92.1 μs & 86 KB \\ -Kronecker\_DenseSmall & 8×8 & 2.31 ms & 1.5 MB \\ -Kronecker\_SparseMedium & 16×16 & 1.20 ms & 229 KB \\ -Kronecker\_DenseMedium & 16×16 & 114 ms & 31 MB \\ -Kronecker\_SparseLarge & 32×32 & 6.22 ms & 112 KB \\ -Kronecker\_DenseLarge & 32×32 & 1.29 s & 576 MB \\ +Kronecker\_SparseSmall & 8$\times$8 & 92.1 μs & 86 KB \\ +Kronecker\_DenseSmall & 8$\times$8 & 2.31 ms & 1.5 MB \\ +Kronecker\_SparseMedium & 16$\times$16 & 1.20 ms & 229 KB \\ +Kronecker\_DenseMedium & 16$\times$16 & 114 ms & 31 MB \\ +Kronecker\_SparseLarge & 32$\times$32 & 6.22 ms & 112 KB \\ +Kronecker\_DenseLarge & 32$\times$32 & 1.29 s & 576 MB \\ \bottomrule \end{tabular} \end{table} -\subsection{Выводы из экспериментов} - -Анализ полученных результатов позволяет ответить на исследовательские вопросы, сформулированные в разделе~3.2. - -\begin{enumerate} - \item \textbf{Редукция матриц (reduceRows, reduceCols)}: разреженные матрицы демонстрируют преимущество над плотными во всех размерах. На малых матрицах (32×32) выигрыш составляет 3-4 раза (64-66 μs против 256-293 μs), на средних (256×256)~--- 30-40 раз (1.7-1.9 ms против 56-78 ms), на больших (1024×1024)~--- до 120 раз (9-10 ms против 856-1137 ms). Аллокации памяти также отличаются в 4, 15 и 60 раз соответственно. Результаты времени выполнения для плотных матриц с единичными и случайными значениями (DenseUniform и DenseRandom) близки, разница не превышает 25\%, разница объёма аллоцированной памяти~--- не более 2\%. - - \item \textbf{Сравнение реализаций reduceCols}: транспонирование эффективнее на плотных матрицах (ускорение растёт с размером: 1.5\%, 11\%, 22\%), но проигрывает на разреженных (замедление 18\%, 51\%, 97\%). Это объясняется лучшей кэш-локальностью при последовательном обходе строк после транспонирования. - - \item \textbf{Срез (slice)}: на всех размерах производительность для разреженных и плотных матриц/векторов остаётся сопоставимой (разница не превышает 10-15\%). - - \item \textbf{Произведение Кронекера}: выигрыш разреженных матриц над плотными растёт с размером. Для матриц 8×8 разреженная быстрее в 25 раз (92 μs против 2.3 ms), для 16×16~--- в 95 раз (1.2 ms против 114 ms), для 32×32~--- в 200 раз (6.2 ms против 1.29 с). Аллокации памяти различаются ещё сильнее: 86 KB против 1.5 MB (8×8), 229 KB против 31 MB (16×16), 112 KB против 576 MB (32×32). Соотношение по памяти достигает 5000 раз на максимальном размере. -\end{enumerate} +Выигрыш разреженных матриц над плотными растёт с размером. Для матриц 8$\times$8 разреженная быстрее в 25 раз (92 μs против 2.3 ms), для 16$\times$16~--- в 95 раз (1.2 ms против 114 ms), для 32$\times$32~--- в 200 раз (6.2 ms против 1.29 с). Аллокации памяти различаются ещё сильнее: 86 KB против 1.5 MB (8$\times$8), 229 KB против 31 MB (16$\times$16), 112 KB против 576 MB (32$\times$32). Соотношение по памяти достигает 5000 раз на максимальном размере. \section*{Заключение} В результате выполнения работы все поставленные задачи были решены. Реализованные операции \texttt{reduceRows}, \texttt{reduceCols}, \texttt{Vector.slice}, \texttt{Matrix.slice}, \texttt{kroneckerProduct} и \texttt{map} прошли модульное тестирование и интегрированы в библиотеку QTreeFSharp. -Экспериментальное исследование показало, что разреженные матрицы на больших размерах (1024×1024) работают в 100–120 раз быстрее плотных и потребляют в 60 раз меньше памяти. Выигрыш растёт с увеличением размера матрицы и уменьшением плотности. +Экспериментальное исследование показало, что разреженные матрицы на больших размерах (1024$\times$1024) работают в 100–120 раз быстрее плотных и потребляют в 60 раз меньше памяти. Выигрыш растёт с увеличением размера матрицы и уменьшением плотности. Полученные результаты задокументированы и могут быть использованы для дальнейшей оптимизации графовых алгоритмов и работы с матрицами. diff --git a/main.tex b/main.tex index 0dbdde6..082895f 100644 --- a/main.tex +++ b/main.tex @@ -40,8 +40,17 @@ \includepdf[pages=-, addtotoc={1, section, 1, {Гаврилов Максим Юрьевич, Программирование микроконтроллеров RISC-V}, gavrilov_maxim}] {Maxim_Gavrilov/Maxim_Gavrilov_report.pdf} +\includepdf[pages=-, + addtotoc={1, section, 1, {Замятина Элла Андреевна, Свёртка изображений}, zamyatina_ella}] +{Ella_Zamyatina/Ella_Zamyatina_report.pdf} +\end{document} + addtotoc={1, section, 1, {Тимофеев Матвей Игоревич, LamaGraph: знакомство с HDL}, timofeev_matvey}] +{Matvey_Timofeev/Matvey_Timofeev_report.pdf} +\includepdf[pages=-, + addtotoc={1, section, 1, {Арзамасцева Екатерина Андреевна, Оптимизация произведения Кронекера для библиотеки SuiteSparse:GraphBLAS}, arzamaszeva_ekaterina}] +{Ekaterina_Arzamaszeva/Ekaterina_Arzamaszeva_report.pdf} +\end{document} \includepdf[pages=-, addtotoc={1, section, 1, {Брулевич Никита Петрович, LaMaGraph: Разреженные матрицы на F\#}, brulevich_nikita}] {Nikita_Brulevich/Nikita_Brulevich_report.pdf} \end{document} -\end{document} From bef9d061df13e342ddbb5ebc77d972544d516b90 Mon Sep 17 00:00:00 2001 From: Brulevich-Nikita Date: Sun, 14 Jun 2026 14:17:15 +0300 Subject: [PATCH 08/12] fix main.tex --- main.tex | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/main.tex b/main.tex index 082895f..c0b13b2 100644 --- a/main.tex +++ b/main.tex @@ -43,14 +43,13 @@ \includepdf[pages=-, addtotoc={1, section, 1, {Замятина Элла Андреевна, Свёртка изображений}, zamyatina_ella}] {Ella_Zamyatina/Ella_Zamyatina_report.pdf} -\end{document} +\includepdf[pages=-, addtotoc={1, section, 1, {Тимофеев Матвей Игоревич, LamaGraph: знакомство с HDL}, timofeev_matvey}] {Matvey_Timofeev/Matvey_Timofeev_report.pdf} \includepdf[pages=-, addtotoc={1, section, 1, {Арзамасцева Екатерина Андреевна, Оптимизация произведения Кронекера для библиотеки SuiteSparse:GraphBLAS}, arzamaszeva_ekaterina}] {Ekaterina_Arzamaszeva/Ekaterina_Arzamaszeva_report.pdf} -\end{document} \includepdf[pages=-, addtotoc={1, section, 1, {Брулевич Никита Петрович, LaMaGraph: Разреженные матрицы на F\#}, brulevich_nikita}] {Nikita_Brulevich/Nikita_Brulevich_report.pdf} -\end{document} +\end{document} \ No newline at end of file From 71650b88b95a2e56ffae74abfe62051a44fda3a7 Mon Sep 17 00:00:00 2001 From: Brulevich-Nikita Date: Sun, 14 Jun 2026 14:23:28 +0300 Subject: [PATCH 09/12] add pdf files --- .../images/rations_generic.pdf | Bin 0 -> 26883 bytes Ekaterina_Arzamaszeva/images/rations_jit.pdf | Bin 0 -> 27083 bytes .../images/time_comparison.pdf | Bin 0 -> 22513 bytes Ella_Zamyatina/benchmark.pdf | Bin 0 -> 25675 bytes Matvey_Timofeev/images/adder_k_numbers.pdf | Bin 0 -> 10152 bytes Matvey_Timofeev/images/lut_peirce_arrow.pdf | Bin 0 -> 8478 bytes Matvey_Timofeev/images/mux_4to1_logic.pdf | Bin 0 -> 9064 bytes .../images/mux_4to1_logic_optimized.pdf | Bin 0 -> 8727 bytes Matvey_Timofeev/images/solution.pdf | Bin 0 -> 8419 bytes 9 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Ekaterina_Arzamaszeva/images/rations_generic.pdf create mode 100644 Ekaterina_Arzamaszeva/images/rations_jit.pdf create mode 100644 Ekaterina_Arzamaszeva/images/time_comparison.pdf create mode 100644 Ella_Zamyatina/benchmark.pdf create mode 100644 Matvey_Timofeev/images/adder_k_numbers.pdf create mode 100644 Matvey_Timofeev/images/lut_peirce_arrow.pdf create mode 100644 Matvey_Timofeev/images/mux_4to1_logic.pdf create mode 100644 Matvey_Timofeev/images/mux_4to1_logic_optimized.pdf create mode 100644 Matvey_Timofeev/images/solution.pdf diff --git a/Ekaterina_Arzamaszeva/images/rations_generic.pdf b/Ekaterina_Arzamaszeva/images/rations_generic.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0a89120a8a9bfa159d0c912b05a70c2c4f07d6c8 GIT binary patch literal 26883 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 literal 0 HcmV?d00001 diff --git a/Ekaterina_Arzamaszeva/images/rations_jit.pdf b/Ekaterina_Arzamaszeva/images/rations_jit.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6bb5a54f39cd8e51f657cf8e465b40f62b4416ba GIT binary patch literal 27083 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 X^LbuR^Fk{D|MwTGtE&%RK34w#2ji5H literal 0 HcmV?d00001 diff --git a/Ekaterina_Arzamaszeva/images/time_comparison.pdf b/Ekaterina_Arzamaszeva/images/time_comparison.pdf new file mode 100644 index 0000000000000000000000000000000000000000..689d89aa94aa50fb59d224fc13850a34fb0c78be GIT binary patch literal 22513 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 literal 0 HcmV?d00001 diff --git a/Ella_Zamyatina/benchmark.pdf b/Ella_Zamyatina/benchmark.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6f8db5020564b8a48b5778288482aeb26ac284ae GIT binary patch literal 25675 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 B$R+>) literal 0 HcmV?d00001 diff --git a/Matvey_Timofeev/images/lut_peirce_arrow.pdf b/Matvey_Timofeev/images/lut_peirce_arrow.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1814b01da8c0e29b88f82e8446975754e57d4ae6 GIT binary patch literal 8478 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 nfy>R`gcUC@j9m> literal 0 HcmV?d00001 diff --git a/Matvey_Timofeev/images/mux_4to1_logic.pdf b/Matvey_Timofeev/images/mux_4to1_logic.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6eb624fd761357d5554c91579fc560615164b365 GIT binary patch literal 9064 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 Vh%@ray264Y!UQZV@(&aU{tqZbxE25a literal 0 HcmV?d00001 diff --git a/Matvey_Timofeev/images/mux_4to1_logic_optimized.pdf b/Matvey_Timofeev/images/mux_4to1_logic_optimized.pdf new file mode 100644 index 0000000000000000000000000000000000000000..68376bcea10e7afc82d3fc5bc0499cd44e719e86 GIT binary patch literal 8727 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 EA8uRcX#fBK literal 0 HcmV?d00001 diff --git a/Matvey_Timofeev/images/solution.pdf b/Matvey_Timofeev/images/solution.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d0656a6d9910fc8af8cdd047ff7dd915ad1af565 GIT binary patch literal 8419 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 literal 0 HcmV?d00001 From f05125451268cd67ab16832a775a3d90b69da9f2 Mon Sep 17 00:00:00 2001 From: Brulevich-Nikita Date: Sun, 14 Jun 2026 20:24:15 +0300 Subject: [PATCH 10/12] fix: mu in report --- Nikita_Brulevich/Nikita_Brulevich_report.tex | 38 ++++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Nikita_Brulevich/Nikita_Brulevich_report.tex b/Nikita_Brulevich/Nikita_Brulevich_report.tex index 8ce055d..f75807f 100644 --- a/Nikita_Brulevich/Nikita_Brulevich_report.tex +++ b/Nikita_Brulevich/Nikita_Brulevich_report.tex @@ -149,8 +149,8 @@ \subsection{Результаты} \midrule \multicolumn{4}{c}{\textbf{Sparse (разреженные, случайные)}} \\ \midrule -ReduceRows\_SparseSmall & 32$\times$32 & 64.2 μs & 67.6 KB \\ -ReduceCols\_SparseSmall & 32$\times$32 & 65.7 μs & 72.7 KB \\ +ReduceRows\_SparseSmall & 32$\times$32 & 64.2 $\mu$s & 67.6 KB \\ +ReduceCols\_SparseSmall & 32$\times$32 & 65.7 $\mu$s & 72.7 KB \\ ReduceRows\_SparseMedium & 256$\times$256 & 1.73 ms & 1.27 MB \\ ReduceCols\_SparseMedium & 256$\times$256 & 1.87 ms & 1.35 MB \\ ReduceRows\_SparseLarge & 1024$\times$1024 & 9.31 ms & 4.59 MB \\ @@ -158,8 +158,8 @@ \subsection{Результаты} \midrule \multicolumn{4}{c}{\textbf{DenseUniform (плотные, все 1.0)}} \\ \midrule -ReduceRows\_DenseUniformSmall & 32$\times$32 & 255.6 μs & 308 KB \\ -ReduceCols\_DenseUniformSmall & 32$\times$32 & 264.5 μs & 313 KB \\ +ReduceRows\_DenseUniformSmall & 32$\times$32 & 255.6 $\mu$s & 308 KB \\ +ReduceCols\_DenseUniformSmall & 32$\times$32 & 264.5 $\mu$s & 313 KB \\ ReduceRows\_DenseUniformMedium & 256$\times$256 & 56.7 ms & 17.6 MB \\ ReduceCols\_DenseUniformMedium & 256$\times$256 & 72.4 ms & 17.6 MB \\ ReduceRows\_DenseUniformLarge & 1024$\times$1024 & 856 ms & 276 MB \\ @@ -167,8 +167,8 @@ \subsection{Результаты} \midrule \multicolumn{4}{c}{\textbf{DenseRandom (плотные, случайные)}} \\ \midrule -ReduceRows\_DenseRandomSmall & 32$\times$32 & 277.6 μs & 308 KB \\ -ReduceCols\_DenseRandomSmall & 32$\times$32 & 293.2 μs & 312 KB \\ +ReduceRows\_DenseRandomSmall & 32$\times$32 & 277.6 $\mu$s & 308 KB \\ +ReduceCols\_DenseRandomSmall & 32$\times$32 & 293.2 $\mu$s & 312 KB \\ ReduceRows\_DenseRandomMedium & 256$\times$256 & 77.9 ms & 17.6 MB \\ ReduceCols\_DenseRandomMedium & 256$\times$256 & 74.6 ms & 17.6 MB \\ ReduceRows\_DenseRandomLarge & 1024$\times$1024 & 1072 ms & 276 MB \\ @@ -177,7 +177,7 @@ \subsection{Результаты} \end{tabular} \end{table} -Разреженные матрицы демонстрируют преимущество над плотными во всех размерах. На малых матрицах (32$\times$32) выигрыш составляет 3-4 раза (64-66 μs против 256-293 μs), на средних (256$\times$256)~--- 30-40 раз (1.7-1.9 ms против 56-78 ms), на больших (1024$\times$1024)~--- до 120 раз (9-10 ms против 856-1137 ms). Аллокации памяти также отличаются в 4, 15 и 60 раз соответственно. Результаты времени выполнения для плотных матриц с единичными и случайными значениями (DenseUniform и DenseRandom) близки, разница не превышает 25\%, разница объёма аллоцированной памяти~--- не более 2\%. +Разреженные матрицы демонстрируют преимущество над плотными во всех размерах. На малых матрицах (32$\times$32) выигрыш составляет 3-4 раза (64-66 $\mu$s против 256-293 $\mu$s), на средних (256$\times$256)~--- 30-40 раз (1.7-1.9 ms против 56-78 ms), на больших (1024$\times$1024)~--- до 120 раз (9-10 ms против 856-1137 ms). Аллокации памяти также отличаются в 4, 15 и 60 раз соответственно. Результаты времени выполнения для плотных матриц с единичными и случайными значениями (DenseUniform и DenseRandom) близки, разница не превышает 25\%, разница объёма аллоцированной памяти~--- не более 2\%. \textbf{Сравнение reduceCols и reduceCols как transpose + reduceRows} @@ -196,8 +196,8 @@ \subsection{Результаты} \cline{3-6} & & Оригинал & Транспонирование & Оригинал & Транспонирование & \\ \midrule -ReduceCols\_SparseSmall & 32$\times$32 & 66.5 μs & 78.5 μs & 72.7 KB & 75.0 KB & +18\% \\ -ReduceCols\_DenseSmall & 32$\times$32 & 265 μs & 261 μs & 313 KB & 310 KB & -1.5\% \\ +ReduceCols\_SparseSmall & 32$\times$32 & 66.5 $\mu$s & 78.5 $\mu$s & 72.7 KB & 75.0 KB & +18\% \\ +ReduceCols\_DenseSmall & 32$\times$32 & 265 $\mu$s & 261 $\mu$s & 313 KB & 310 KB & -1.5\% \\ ReduceCols\_SparseMedium & 256$\times$256 & 1.84 ms & 2.78 ms & 1.35 MB & 1.40 MB & +51\% \\ ReduceCols\_DenseMedium & 256$\times$256 & 64.8 ms & 57.5 ms & 17.6 MB & 17.6 MB & \textbf{-11\%} \\ ReduceCols\_SparseLarge & 1024$\times$1024 & 9.89 ms & 19.5 ms & 4.97 MB & 5.10 MB & +97\% \\ @@ -234,12 +234,12 @@ \subsection{Результаты} \toprule Метод & Размер & Время (Mean) & Аллокации \\ \midrule -Slice\_SparseSmall & 32 & 2.6 μs & 3.8 KB \\ -Slice\_DenseSmall & 32 & 2.8 μs & 4.5 KB \\ -Slice\_SparseMedium & 256 & 29.7 μs & 42.5 KB \\ -Slice\_DenseMedium & 256 & 31.6 μs & 46.3 KB \\ -Slice\_SparseLarge & 1024 & 181 μs & 212 KB \\ -Slice\_DenseLarge & 1024 & 178 μs & 216 KB \\ +Slice\_SparseSmall & 32 & 2.6 $\mu$s & 3.8 KB \\ +Slice\_DenseSmall & 32 & 2.8 $\mu$s & 4.5 KB \\ +Slice\_SparseMedium & 256 & 29.7 $\mu$s & 42.5 KB \\ +Slice\_DenseMedium & 256 & 31.6 $\mu$s & 46.3 KB \\ +Slice\_SparseLarge & 1024 & 181 $\mu$s & 212 KB \\ +Slice\_DenseLarge & 1024 & 178 $\mu$s & 216 KB \\ \bottomrule \end{tabular} \end{table} @@ -253,8 +253,8 @@ \subsection{Результаты} \toprule Метод & Размер & Время (Mean) & Аллокации \\ \midrule -MatrixSlice\_SparseSmall & 32$\times$32 & 68.8 μs & 68 KB \\ -MatrixSlice\_DenseSmall & 32$\times$32 & 53.3 μs & 77 KB \\ +MatrixSlice\_SparseSmall & 32$\times$32 & 68.8 $\mu$s & 68 KB \\ +MatrixSlice\_DenseSmall & 32$\times$32 & 53.3 $\mu$s & 77 KB \\ MatrixSlice\_SparseMedium & 256$\times$256 & 14.0 ms & 6.9 MB \\ MatrixSlice\_DenseMedium & 256$\times$256 & 15.0 ms & 7.2 MB \\ MatrixSlice\_SparseLarge & 1024$\times$1024 & 285 ms & 138 MB \\ @@ -274,7 +274,7 @@ \subsection{Результаты} \toprule Метод & Исходный размер & Время (Mean) & Аллокации \\ \midrule -Kronecker\_SparseSmall & 8$\times$8 & 92.1 μs & 86 KB \\ +Kronecker\_SparseSmall & 8$\times$8 & 92.1 $\mu$s & 86 KB \\ Kronecker\_DenseSmall & 8$\times$8 & 2.31 ms & 1.5 MB \\ Kronecker\_SparseMedium & 16$\times$16 & 1.20 ms & 229 KB \\ Kronecker\_DenseMedium & 16$\times$16 & 114 ms & 31 MB \\ @@ -284,7 +284,7 @@ \subsection{Результаты} \end{tabular} \end{table} -Выигрыш разреженных матриц над плотными растёт с размером. Для матриц 8$\times$8 разреженная быстрее в 25 раз (92 μs против 2.3 ms), для 16$\times$16~--- в 95 раз (1.2 ms против 114 ms), для 32$\times$32~--- в 200 раз (6.2 ms против 1.29 с). Аллокации памяти различаются ещё сильнее: 86 KB против 1.5 MB (8$\times$8), 229 KB против 31 MB (16$\times$16), 112 KB против 576 MB (32$\times$32). Соотношение по памяти достигает 5000 раз на максимальном размере. +Выигрыш разреженных матриц над плотными растёт с размером. Для матриц 8$\times$8 разреженная быстрее в 25 раз (92 $\mu$s против 2.3 ms), для 16$\times$16~--- в 95 раз (1.2 ms против 114 ms), для 32$\times$32~--- в 200 раз (6.2 ms против 1.29 с). Аллокации памяти различаются ещё сильнее: 86 KB против 1.5 MB (8$\times$8), 229 KB против 31 MB (16$\times$16), 112 KB против 576 MB (32$\times$32). Соотношение по памяти достигает 5000 раз на максимальном размере. \section*{Заключение} В результате выполнения работы все поставленные задачи были решены. Реализованные операции \texttt{reduceRows}, \texttt{reduceCols}, \texttt{Vector.slice}, \texttt{Matrix.slice}, \texttt{kroneckerProduct} и \texttt{map} прошли модульное тестирование и интегрированы в библиотеку QTreeFSharp. From 38f6cc700582a5a8444cef829c027165e31ff036 Mon Sep 17 00:00:00 2001 From: Brulevich-Nikita Date: Mon, 15 Jun 2026 14:48:52 +0300 Subject: [PATCH 11/12] fix: dots, comments and more in report --- Nikita_Brulevich/Nikita_Brulevich_report.tex | 40 ++++++++++---------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/Nikita_Brulevich/Nikita_Brulevich_report.tex b/Nikita_Brulevich/Nikita_Brulevich_report.tex index f75807f..210588b 100644 --- a/Nikita_Brulevich/Nikita_Brulevich_report.tex +++ b/Nikita_Brulevich/Nikita_Brulevich_report.tex @@ -53,7 +53,7 @@ \section*{Введение} -Работа выполняется в рамках проекта \textbf{LamaGraph} (Lambdas, Matrices and Graphs), нацеленного на разработку прототипа быстрого вычислителя для разреженной линейной алгебры, реализованного в функциональной парадигме программирования на языке F\#. +Работа выполняется в рамках проекта \textbf{LamaGraph} (Lambdas, Matrices and Graphs), нацеленного на разработку прототипа вычислителя для разреженной линейной алгебры на основе деревьев квадрантов, реализованного на языке F\#. Одной из ключевых частей проекта является библиотека \textbf{QTreeFSharp} для работы с разреженными матрицами и векторами, реализованная на деревьях квадрантов (quadtree). Данная библиотека служит основой для реализации графовых алгоритмов (BFS, SSSP, поиск треугольников, построение MST) и требует расширения набором операций для работы с матрицами и векторами. @@ -63,7 +63,7 @@ \section{Постановка задачи} \textbf{Целью работы} является реализация и оптимизация операций над разреженными матрицами и векторами (редукция строк и столбцов, срез векторов и матриц, произведение Кронекера, преобразование каждого ненулевого элемента матрицы) для библиотеки QTreeFSharp. -Для достижения цели были поставлены и решены следующие задачи: +Для достижения цели были поставлены и решены следующие задачи. \begin{enumerate} \item Разработать и реализовать недостающие операции в соответствии с архитектурой библиотеки QTreeFSharp. \item Написать модульные тесты для проверки корректности реализованных функций. @@ -79,7 +79,7 @@ \section{Обзор} \subsection{Исследовательские вопросы} -В ходе экспериментального исследования предполагается ответить на следующие вопросы: +В ходе экспериментального исследования предполагается ответить на следующие вопросы. \begin{enumerate} \item Как зависит производительность операций над разреженными матрицами от плотности и размера матрицы? @@ -91,21 +91,23 @@ \section{Описание предлагаемого решения} В проекте QTreeFSharp уже была реализована основа для работы с разреженными матрицами и векторами. Разреженные векторы представлены бинарным деревом (\texttt{btree}), где листья содержат \texttt{UserValue} или \texttt{Dummy}. Размер дерева округляется до ближайшей степени двойки. Разреженные матрицы реализованы на дереве квадрантов (\texttt{qtree}) с четырьмя подузлами (NW, NE, SW, SE), что позволяет рекурсивно делить матрицу на квадранты. +\textbf{Реализованные операции.} В рамках расширения библиотеки были реализованы и оптимизированы следующие операции: - \begin{itemize} - \item \texttt{reduceRows}, \texttt{reduceCols}~--- свёртка матрицы в вектор с использованием заданной бинарной операции по строкам и по столбцам соответственно - \item \texttt{slice}~--- выделение подматрицы/подвектора по заданным границам - \item \texttt{kroneckerProduct}~--- произведение Кронекера двух матриц - \item \texttt{map}~--- применение функции к каждому ненулевому элементу матрицы + \item \texttt{reduceRows}, \texttt{reduceCols}~--- свёртка матрицы в вектор с использованием заданной бинарной операции по строкам и по столбцам соответственно. + \item \texttt{slice}~--- выделение подматрицы/подвектора по заданным границам. + \item \texttt{kroneckerProduct}~--- произведение Кронекера двух матриц. + \item \texttt{map}~--- применение функции к каждому ненулевому элементу матрицы. \end{itemize} -Также была изменена сигнатура функции fromCoordinateList в Matrix.fs и Vector.fs, добавлена валидация аргументов. +\textbf{Изменения существующих функций.} +Была изменена реализация функции \texttt{fromCoordinateList} в \texttt{Matrix.fs} и \texttt{Vector.fs}: добавлена проверка выхода индексов за границы, обработка дублирующихся координат (берётся последнее значение) и возврат \texttt{Result} с сообщением об ошибке. +\textbf{Сравнение реализаций \texttt{reduceCols}.} Проведено сравнение двух способов реализации \texttt{reduceCols}: \begin{enumerate} - \item Прямой обход по столбцам (оригинальная реализация) - \item Транспонирование матрицы с последующей свёрткой по строкам (альтернативный подход с учётом уже реализованной в проекте функции transpose). + \item прямой обход по столбцам (оригинальная реализация); + \item транспонирование матрицы с последующей свёрткой по строкам (альтернативный подход с использованием уже реализованной в проекте функции \texttt{transpose}). \end{enumerate} \textbf{Тестирование.} @@ -118,7 +120,7 @@ \section{Описание предлагаемого решения} \item \texttt{Matrix.reduceCols}~--- 7 тестов \item \texttt{Matrix.kroneckerProduct}~--- 13 тестов \end{itemize} -Кроме того, добавлены отсутствующие тесты на уже имевшиеся функции --- 17 тестов. +Кроме того, добавлены отсутствующие тесты на уже имевшиеся функции~--- 17 тестов. \section{Эксперименты} @@ -177,7 +179,7 @@ \subsection{Результаты} \end{tabular} \end{table} -Разреженные матрицы демонстрируют преимущество над плотными во всех размерах. На малых матрицах (32$\times$32) выигрыш составляет 3-4 раза (64-66 $\mu$s против 256-293 $\mu$s), на средних (256$\times$256)~--- 30-40 раз (1.7-1.9 ms против 56-78 ms), на больших (1024$\times$1024)~--- до 120 раз (9-10 ms против 856-1137 ms). Аллокации памяти также отличаются в 4, 15 и 60 раз соответственно. Результаты времени выполнения для плотных матриц с единичными и случайными значениями (DenseUniform и DenseRandom) близки, разница не превышает 25\%, разница объёма аллоцированной памяти~--- не более 2\%. +На малых матрицах (32$\times$32) выигрыш составляет 3--4 раза (64--66 $\mu$s против 256--293 $\mu$s), на средних (256$\times$256)~--- 30--40 раз (1.7--1.9 ms против 56--78 ms), на больших (1024$\times$1024)~--- до 120 раз (9--10 ms против 856--1137 ms). Аллокации памяти также отличаются в 4, 15 и 60 раз соответственно. Результаты времени выполнения для плотных матриц с единичными и случайными значениями (DenseUniform и DenseRandom) близки, разница не превышает 25\%, разница объёма аллоцированной памяти~--- не более 2\%. \textbf{Сравнение reduceCols и reduceCols как transpose + reduceRows} @@ -201,7 +203,7 @@ \subsection{Результаты} ReduceCols\_SparseMedium & 256$\times$256 & 1.84 ms & 2.78 ms & 1.35 MB & 1.40 MB & +51\% \\ ReduceCols\_DenseMedium & 256$\times$256 & 64.8 ms & 57.5 ms & 17.6 MB & 17.6 MB & \textbf{-11\%} \\ ReduceCols\_SparseLarge & 1024$\times$1024 & 9.89 ms & 19.5 ms & 4.97 MB & 5.10 MB & +97\% \\ -ReduceCols\_DenseLarge & 1024$\times$1024 & 1.14 s & 0.89 s & 277 MB & 277 MB & \textbf{-22\%} \\ +ReduceCols\_DenseLarge & 1024$\times$1024 & 1140 ms & 890 ms & 277 MB & 277 MB & \textbf{-22\%} \\ \bottomrule \end{tabular} } @@ -211,19 +213,19 @@ \subsection{Результаты} \begin{figure}[H] \centering -\includegraphics[width=0.85\textwidth]{time_comparison.pdf} +\includegraphics[width=0.80\textwidth]{time_comparison.pdf} \caption{Сравнение времени выполнения оригинального reduceCols и реализации через транспонирование} \label{fig:reducecols_time} \end{figure} \begin{figure}[H] \centering -\includegraphics[width=0.85\textwidth]{memory_comparison.pdf} +\includegraphics[width=0.80\textwidth]{memory_comparison.pdf} \caption{Сравнение аллокаций памяти оригинального reduceCols и реализации через транспонирование} \label{fig:reducecols_memory} \end{figure} -Вывод из сравнения реализаций reduceCols: транспонирование эффективнее на плотных матрицах (ускорение растёт с размером: 1.5\%, 11\%, 22\%), но проигрывает на разреженных (замедление 18\%, 51\%, 97\%). Это объясняется лучшей кэш-локальностью при последовательном обходе строк после транспонирования. +Вывод из сравнения реализаций reduceCols: транспонирование эффективнее на плотных матрицах (ускорение растёт с размером: 1.5\%, 11\%, 22\%), но проигрывает на разреженных (замедление 18\%, 51\%, 97\%). \textbf{Slice для векторов} @@ -263,7 +265,7 @@ \subsection{Результаты} \end{tabular} \end{table} -На всех размерах производительность среза (slice) для разреженных и плотных матриц/векторов остаётся сопоставимой (разница не превышает 10-15\%). +На всех размерах производительность среза (slice) для разреженных и плотных матриц/векторов остаётся сопоставимой (разница не превышает 10--15\%). \textbf{Произведение Кронекера} @@ -279,7 +281,7 @@ \subsection{Результаты} Kronecker\_SparseMedium & 16$\times$16 & 1.20 ms & 229 KB \\ Kronecker\_DenseMedium & 16$\times$16 & 114 ms & 31 MB \\ Kronecker\_SparseLarge & 32$\times$32 & 6.22 ms & 112 KB \\ -Kronecker\_DenseLarge & 32$\times$32 & 1.29 s & 576 MB \\ +Kronecker\_DenseLarge & 32$\times$32 & 1290 ms & 576 MB \\ \bottomrule \end{tabular} \end{table} From 33911acb7b77cbaf9fa3f2d9b6f3bc0c394ff271 Mon Sep 17 00:00:00 2001 From: Brulevich-Nikita Date: Mon, 15 Jun 2026 15:07:20 +0300 Subject: [PATCH 12/12] fix range in conclusion: 100--120 --- Nikita_Brulevich/Nikita_Brulevich_report.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Nikita_Brulevich/Nikita_Brulevich_report.tex b/Nikita_Brulevich/Nikita_Brulevich_report.tex index 210588b..f92660a 100644 --- a/Nikita_Brulevich/Nikita_Brulevich_report.tex +++ b/Nikita_Brulevich/Nikita_Brulevich_report.tex @@ -291,7 +291,7 @@ \subsection{Результаты} \section*{Заключение} В результате выполнения работы все поставленные задачи были решены. Реализованные операции \texttt{reduceRows}, \texttt{reduceCols}, \texttt{Vector.slice}, \texttt{Matrix.slice}, \texttt{kroneckerProduct} и \texttt{map} прошли модульное тестирование и интегрированы в библиотеку QTreeFSharp. -Экспериментальное исследование показало, что разреженные матрицы на больших размерах (1024$\times$1024) работают в 100–120 раз быстрее плотных и потребляют в 60 раз меньше памяти. Выигрыш растёт с увеличением размера матрицы и уменьшением плотности. +Экспериментальное исследование показало, что разреженные матрицы на больших размерах (1024$\times$1024) работают в 100-–120 раз быстрее плотных и потребляют в 60 раз меньше памяти. Выигрыш растёт с увеличением размера матрицы и уменьшением плотности. Полученные результаты задокументированы и могут быть использованы для дальнейшей оптимизации графовых алгоритмов и работы с матрицами.