diff --git a/Nikita_Brulevich/Nikita_Brulevich_report.tex b/Nikita_Brulevich/Nikita_Brulevich_report.tex new file mode 100644 index 0000000..f92660a --- /dev/null +++ b/Nikita_Brulevich/Nikita_Brulevich_report.tex @@ -0,0 +1,309 @@ +\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{CMU Serif} +\setsansfont{CMU Sans Serif} +\setmonofont{CMU Typewriter Text} + +\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}} +\overfullrule=5pt + +\usepackage{hyperref} +\usepackage{bookmark} +\usepackage{csquotes} +\usepackage{booktabs} +\usepackage{multirow} + +\title{LaMaGraph: Разреженные матрицы на F\#} + +\author{Брулевич Никита Петрович} + +\date{} + +\begin{document} + +\sloppy + +\maketitle + +\begin{flushright} + Группа: \emph{2025.Б-73-мм} + + Кафедра: \emph{кафедра системного программирования} + + Научный руководитель: \emph{Григорьев Семён Вячеславович} + + Номер семестра практики: \emph{2} +\end{flushright} + +\section*{Введение} + +Работа выполняется в рамках проекта \textbf{LamaGraph} (Lambdas, Matrices and Graphs), нацеленного на разработку прототипа вычислителя для разреженной линейной алгебры на основе деревьев квадрантов, реализованного на языке F\#. + +Одной из ключевых частей проекта является библиотека \textbf{QTreeFSharp} для работы с разреженными матрицами и векторами, реализованная на деревьях квадрантов (quadtree). Данная библиотека служит основой для реализации графовых алгоритмов (BFS, SSSP, поиск треугольников, построение MST) и требует расширения набором операций для работы с матрицами и векторами. + +В данном отчёте представлены результаты работы по реализации и оптимизации некоторых операций над разреженными матрицами и векторами в рамках учебной практики. + +\section{Постановка задачи} + +\textbf{Целью работы} является реализация и оптимизация операций над разреженными матрицами и векторами (редукция строк и столбцов, срез векторов и матриц, произведение Кронекера, преобразование каждого ненулевого элемента матрицы) для библиотеки QTreeFSharp. + +Для достижения цели были поставлены и решены следующие задачи. +\begin{enumerate} + \item Разработать и реализовать недостающие операции в соответствии с архитектурой библиотеки QTreeFSharp. + \item Написать модульные тесты для проверки корректности реализованных функций. + \item Провести замеры производительности по скорости и памяти, сравнить различные подходы к реализации \texttt{reduceCols} (прямой обход по столбцам vs транспонирование). + \item Проанализировать полученные результаты и оценить эффективность реализованных операций на структурах разного размера и плотности. +\end{enumerate} + +\section{Обзор} + +Основная идея библиотеки QTreeFSharp заключается в использовании деревьев квадрантов для представления разреженных матриц. + +В отличие от традиционных форматов (CSR, COO), деревья квадрантов позволяют эффективно выполнять рекурсивные операции за счёт логарифмической сложности доступа и возможности схлопывания одинаковых значений в один лист (UserValue(v)). + +\subsection{Исследовательские вопросы} + +В ходе экспериментального исследования предполагается ответить на следующие вопросы. + +\begin{enumerate} + \item Как зависит производительность операций над разреженными матрицами от плотности и размера матрицы? + \item Какой способ реализации операции reduceCols (прямой обход по столбцам или транспонирование с последующей свёрткой по строкам) обеспечивает лучшую производительность? + \item Как масштабируются операции slice и kroneckerProduct при увеличении размера матрицы? +\end{enumerate} + +\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}~--- применение функции к каждому ненулевому элементу матрицы. +\end{itemize} + +\textbf{Изменения существующих функций.} +Была изменена реализация функции \texttt{fromCoordinateList} в \texttt{Matrix.fs} и \texttt{Vector.fs}: добавлена проверка выхода индексов за границы, обработка дублирующихся координат (берётся последнее значение) и возврат \texttt{Result} с сообщением об ошибке. + +\textbf{Сравнение реализаций \texttt{reduceCols}.} +Проведено сравнение двух способов реализации \texttt{reduceCols}: +\begin{enumerate} + \item прямой обход по столбцам (оригинальная реализация); + \item транспонирование матрицы с последующей свёрткой по строкам (альтернативный подход с использованием уже реализованной в проекте функции \texttt{transpose}). +\end{enumerate} + +\textbf{Тестирование.} +Для каждой из новых реализованных функций написаны 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{Результаты} + +\textbf{ReduceRows и ReduceCols} + +Результаты замеров производительности операций редукции приведены в табл.~\ref{tab:reduce}. + +\begin{table}[H] +\centering +\caption{Результаты Reduce бенчмарков} +\label{tab:reduce} +\begin{tabular}{lccc} +\toprule +Метод & Размер & Время (Mean) & Аллокации \\ +\midrule +\multicolumn{4}{c}{\textbf{Sparse (разреженные, случайные)}} \\ +\midrule +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 \\ +ReduceCols\_SparseLarge & 1024$\times$1024 & 10.16 ms & 4.97 MB \\ +\midrule +\multicolumn{4}{c}{\textbf{DenseUniform (плотные, все 1.0)}} \\ +\midrule +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 \\ +ReduceCols\_DenseUniformLarge & 1024$\times$1024 & 1137 ms & 277 MB \\ +\midrule +\multicolumn{4}{c}{\textbf{DenseRandom (плотные, случайные)}} \\ +\midrule +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 \\ +ReduceCols\_DenseRandomLarge & 1024$\times$1024 & 1106 ms & 277 MB \\ +\bottomrule +\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\%. + + +\textbf{Сравнение reduceCols и reduceCols как transpose + reduceRows} + +Сравнение производительности двух реализаций приведено в табл.~\ref{tab:reducecols}. + +\begin{table}[H] +\centering +\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}{*}{Разница по времени} \\ +\cline{3-6} +& & Оригинал & Транспонирование & Оригинал & Транспонирование & \\ +\midrule +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\% \\ +ReduceCols\_DenseLarge & 1024$\times$1024 & 1140 ms & 890 ms & 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.80\textwidth]{time_comparison.pdf} +\caption{Сравнение времени выполнения оригинального reduceCols и реализации через транспонирование} +\label{fig:reducecols_time} +\end{figure} + +\begin{figure}[H] +\centering +\includegraphics[width=0.80\textwidth]{memory_comparison.pdf} +\caption{Сравнение аллокаций памяти оригинального reduceCols и реализации через транспонирование} +\label{fig:reducecols_memory} +\end{figure} + +Вывод из сравнения реализаций reduceCols: транспонирование эффективнее на плотных матрицах (ускорение растёт с размером: 1.5\%, 11\%, 22\%), но проигрывает на разреженных (замедление 18\%, 51\%, 97\%). + +\textbf{Slice для векторов} + +\begin{table}[H] +\centering +\caption{Результаты VectorSlice (срез середины)} +\begin{tabular}{lccc} +\toprule +Метод & Размер & Время (Mean) & Аллокации \\ +\midrule +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} + +\textbf{Slice для матриц} + +\begin{table}[H] +\centering +\caption{Результаты MatrixSlice (срез середины)} +\begin{tabular}{lccc} +\toprule +Метод & Размер & Время (Mean) & Аллокации \\ +\midrule +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 \\ +MatrixSlice\_DenseLarge & 1024$\times$1024 & 302 ms & 139 MB \\ +\bottomrule +\end{tabular} +\end{table} + +На всех размерах производительность среза (slice) для разреженных и плотных матриц/векторов остаётся сопоставимой (разница не превышает 10--15\%). + +\textbf{Произведение Кронекера} + +\begin{table}[H] +\centering +\caption{Результаты KroneckerProduct} +\begin{tabular}{lccc} +\toprule +Метод & Исходный размер & Время (Mean) & Аллокации \\ +\midrule +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 \\ +Kronecker\_SparseLarge & 32$\times$32 & 6.22 ms & 112 KB \\ +Kronecker\_DenseLarge & 32$\times$32 & 1290 ms & 576 MB \\ +\bottomrule +\end{tabular} +\end{table} + +Выигрыш разреженных матриц над плотными растёт с размером. Для матриц 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. + +Экспериментальное исследование показало, что разреженные матрицы на больших размерах (1024$\times$1024) работают в 100-–120 раз быстрее плотных и потребляют в 60 раз меньше памяти. Выигрыш растёт с увеличением размера матрицы и уменьшением плотности. + +Полученные результаты задокументированы и могут быть использованы для дальнейшей оптимизации графовых алгоритмов и работы с матрицами. + +Исходный код доступен в репозитории: \url{https://github.com/Brulevich-Nikita/QTreeFSharp1} + +\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} + +\end{document} diff --git a/Nikita_Brulevich/memory_comparison.pdf b/Nikita_Brulevich/memory_comparison.pdf new file mode 100644 index 0000000..cd5fcaf Binary files /dev/null and b/Nikita_Brulevich/memory_comparison.pdf differ diff --git a/Nikita_Brulevich/time_comparison.pdf b/Nikita_Brulevich/time_comparison.pdf new file mode 100644 index 0000000..c4b056a Binary files /dev/null and b/Nikita_Brulevich/time_comparison.pdf differ diff --git a/main.tex b/main.tex index b3358cc..ce590b4 100644 --- a/main.tex +++ b/main.tex @@ -65,4 +65,7 @@ \includepdf[pages=-, addtotoc={1, section, 1, {Арзамасцева Екатерина Андреевна, Оптимизация произведения Кронекера для библиотеки SuiteSparse:GraphBLAS}, arzamaszeva_ekaterina}] {Ekaterina_Arzamaszeva/Ekaterina_Arzamaszeva_report.pdf} +\includepdf[pages=-, + addtotoc={1, section, 1, {Брулевич Никита Петрович, LaMaGraph: Разреженные матрицы на F\#}, brulevich_nikita}] +{Nikita_Brulevich/Nikita_Brulevich_report.pdf} \end{document}