From 5d0749bf79677b6c80e21b94e9f7fa1b525456cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B0=D0=BD=D0=B8=D0=BB=D0=B0=20=D0=9C=D1=83=D1=82?= =?UTF-8?q?=D1=80=D0=B8=D1=81=D0=BA=D0=BE=D0=B2?= Date: Tue, 9 Jan 2024 23:45:45 +0400 Subject: [PATCH] =?UTF-8?q?=D0=9B=D0=B0=D0=B1=D0=B0=205?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tasks/mutriskov-ds/lab_5/.gitignore | 477 ++++++++++++++++++++++ tasks/mutriskov-ds/lab_5/README.md | 191 +++++++++ tasks/mutriskov-ds/lab_5/Task/Program.cs | 167 ++++++++ tasks/mutriskov-ds/lab_5/Task/Task.csproj | 14 + tasks/mutriskov-ds/lab_5/Task/Task.sln | 22 + tasks/mutriskov-ds/lab_5/images/1.png | Bin 0 -> 30250 bytes 6 files changed, 871 insertions(+) create mode 100644 tasks/mutriskov-ds/lab_5/.gitignore create mode 100644 tasks/mutriskov-ds/lab_5/README.md create mode 100644 tasks/mutriskov-ds/lab_5/Task/Program.cs create mode 100644 tasks/mutriskov-ds/lab_5/Task/Task.csproj create mode 100644 tasks/mutriskov-ds/lab_5/Task/Task.sln create mode 100644 tasks/mutriskov-ds/lab_5/images/1.png diff --git a/tasks/mutriskov-ds/lab_5/.gitignore b/tasks/mutriskov-ds/lab_5/.gitignore new file mode 100644 index 0000000..154e127 --- /dev/null +++ b/tasks/mutriskov-ds/lab_5/.gitignore @@ -0,0 +1,477 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk diff --git a/tasks/mutriskov-ds/lab_5/README.md b/tasks/mutriskov-ds/lab_5/README.md new file mode 100644 index 0000000..7572602 --- /dev/null +++ b/tasks/mutriskov-ds/lab_5/README.md @@ -0,0 +1,191 @@ +# Отчёт по лабораторной работе №5 + +Выполнил: студент гр. ИСЭбд-41 Мутрисков Д.С. + +## Создание приложения + +В приложении были созданы следующие методы: + +- Заполнение матрицы рандомными значениями: +``` + private static int[][] GenerateRandomMatrix(int rows, int cols) + { + int[][] matrix = new int[rows][]; + + Random rand = new Random(); + + for (int i = 0; i < rows; i++) + { + matrix[i] = new int[cols]; + for (int j = 0; j < cols; j++) + { + matrix[i][j] = rand.Next(1, 10); + } + } + + return matrix; + } +``` + +- Перемножение матриц обычным алгоритмом: +``` + public static int[][] MultiplySequential(int[][] matrixA, int[][] matrixB) + { + int rowsA = matrixA.Length; + int colsA = matrixA[0].Length; + int colsB = matrixB[0].Length; + + int[][] result = new int[rowsA][]; + + for (int i = 0; i < rowsA; i++) + { + result[i] = new int[colsB]; + + for (int j = 0; j < colsB; j++) + { + for (int k = 0; k < colsA; k++) + { + result[i][j] += matrixA[i][k] * matrixB[k][j]; + } + } + } + + return result; + } +``` + +- Перемножение матриц параллельным алгоритмом: +``` + public static int[][] MultiplyParallel(int[][] matrixA, int[][] matrixB, int numThreads) + { + int rowsA = matrixA.Length; + int colsA = matrixA[0].Length; + int colsB = matrixB[0].Length; + + int[][] result = new int[rowsA][]; + + Parallel.For(0, rowsA, new ParallelOptions { MaxDegreeOfParallelism = numThreads }, i => + { + result[i] = new int[colsB]; + + for (int j = 0; j < colsB; j++) + { + for (int k = 0; k < colsA; k++) + { + result[i][j] += matrixA[i][k] * matrixB[k][j]; + } + } + }); + + return result; + } +``` + +- Создание матриц различных размеров и с различным количеством потоков для параллельного алгоритма: +``` + [Benchmark] + public void MultiplySequential_100x100() + { + int[][] matrixA = GenerateRandomMatrix(100, 100); + int[][] matrixB = GenerateRandomMatrix(100, 100); + MultiplySequential(matrixA, matrixB); + } + + [Benchmark] + public void MultiplyParallel_100x100_4TH() + { + int[][] matrixA = GenerateRandomMatrix(100, 100); + int[][] matrixB = GenerateRandomMatrix(100, 100); + MultiplyParallel(matrixA, matrixB, 4); + } + [Benchmark] + public void MultiplyParallel_100x100_8TH() + { + int[][] matrixA = GenerateRandomMatrix(100, 100); + int[][] matrixB = GenerateRandomMatrix(100, 100); + MultiplyParallel(matrixA, matrixB, 8); + + } + [Benchmark] + public void MultiplyParallel_100x100_16TH() + { + int[][] matrixA = GenerateRandomMatrix(100, 100); + int[][] matrixB = GenerateRandomMatrix(100, 100); + MultiplyParallel(matrixA, matrixB, 16); + + } + + [Benchmark] + public void MultiplySequential_300x300() + { + int[][] matrixA = GenerateRandomMatrix(300, 300); + int[][] matrixB = GenerateRandomMatrix(300, 300); + MultiplySequential(matrixA, matrixB); + } + + [Benchmark] + public void MultiplyParallel_300x300_4TH() + { + int[][] matrixA = GenerateRandomMatrix(300, 300); + int[][] matrixB = GenerateRandomMatrix(300, 300); + MultiplyParallel(matrixA, matrixB, 4); + } + [Benchmark] + public void MultiplyParallel_300x300_8TH() + { + int[][] matrixA = GenerateRandomMatrix(300, 300); + int[][] matrixB = GenerateRandomMatrix(300, 300); + MultiplyParallel(matrixA, matrixB, 8); + } + [Benchmark] + public void MultiplyParallel_300x300_16TH() + { + int[][] matrixA = GenerateRandomMatrix(300, 300); + int[][] matrixB = GenerateRandomMatrix(300, 300); + MultiplyParallel(matrixA, matrixB, 16); + } + [Benchmark] + public void MultiplySequential_500x500() + { + int[][] matrixA = GenerateRandomMatrix(500, 500); + int[][] matrixB = GenerateRandomMatrix(500, 500); + MultiplySequential(matrixA, matrixB); + } + + [Benchmark] + public void MultiplyParallel_500x500_4TH() + { + int[][] matrixA = GenerateRandomMatrix(500, 500); + int[][] matrixB = GenerateRandomMatrix(500, 500); + MultiplyParallel(matrixA, matrixB, 4); + } + [Benchmark] + public void MultiplyParallel_500x500_8TH() + { + int[][] matrixA = GenerateRandomMatrix(500, 500); + int[][] matrixB = GenerateRandomMatrix(500, 500); + MultiplyParallel(matrixA, matrixB, 8); + } + [Benchmark] + public void MultiplyParallel_500x500_16TH() + { + int[][] matrixA = GenerateRandomMatrix(500, 500); + int[][] matrixB = GenerateRandomMatrix(500, 500); + MultiplyParallel(matrixA, matrixB, 16); + } +``` + +- Запуск приложения: +``` + static void Main(string[] args) + { + var summary = BenchmarkRunner.Run(); + Console.ReadLine(); + } +``` + +## Результаты работы приложения + +![](images/1.png) + +По результатам работы: для матриц небольших размеров большое количество потоков не ускоряет (а в некоторых случаях замедляет) работу алгоритма, за счет излишнего переключения процессора. Для больших матриц увеличение количества потоков увеличивает скорость работы алгоритма. В сравнении с однопоточным алгоритмом, работа параллельного в несколько раз быстрее. \ No newline at end of file diff --git a/tasks/mutriskov-ds/lab_5/Task/Program.cs b/tasks/mutriskov-ds/lab_5/Task/Program.cs new file mode 100644 index 0000000..a01047b --- /dev/null +++ b/tasks/mutriskov-ds/lab_5/Task/Program.cs @@ -0,0 +1,167 @@ +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Running; + +var summary = BenchmarkRunner.Run(); +Console.ReadLine(); + +public class MatrixMultiplication +{ + public static int[][] MultiplySequential(int[][] matrixA, int[][] matrixB) + { + int rowsA = matrixA.Length; + int colsA = matrixA[0].Length; + int colsB = matrixB[0].Length; + + int[][] result = new int[rowsA][]; + + for (int i = 0; i < rowsA; i++) + { + result[i] = new int[colsB]; + + for (int j = 0; j < colsB; j++) + { + for (int k = 0; k < colsA; k++) + { + result[i][j] += matrixA[i][k] * matrixB[k][j]; + } + } + } + + return result; + } + + public static int[][] MultiplyParallel(int[][] matrixA, int[][] matrixB, int numThreads) + { + int rowsA = matrixA.Length; + int colsA = matrixA[0].Length; + int colsB = matrixB[0].Length; + + int[][] result = new int[rowsA][]; + + Parallel.For(0, rowsA, new ParallelOptions { MaxDegreeOfParallelism = numThreads }, i => + { + result[i] = new int[colsB]; + + for (int j = 0; j < colsB; j++) + { + for (int k = 0; k < colsA; k++) + { + result[i][j] += matrixA[i][k] * matrixB[k][j]; + } + } + }); + + return result; + } + + [Benchmark] + public void MultiplySequential_100x100() + { + int[][] matrixA = GenerateRandomMatrix(100, 100); + int[][] matrixB = GenerateRandomMatrix(100, 100); + MultiplySequential(matrixA, matrixB); + } + + [Benchmark] + public void MultiplyParallel_100x100_4TH() + { + int[][] matrixA = GenerateRandomMatrix(100, 100); + int[][] matrixB = GenerateRandomMatrix(100, 100); + MultiplyParallel(matrixA, matrixB, 4); + } + [Benchmark] + public void MultiplyParallel_100x100_8TH() + { + int[][] matrixA = GenerateRandomMatrix(100, 100); + int[][] matrixB = GenerateRandomMatrix(100, 100); + MultiplyParallel(matrixA, matrixB, 8); + + } + [Benchmark] + public void MultiplyParallel_100x100_16TH() + { + int[][] matrixA = GenerateRandomMatrix(100, 100); + int[][] matrixB = GenerateRandomMatrix(100, 100); + MultiplyParallel(matrixA, matrixB, 16); + + } + + [Benchmark] + public void MultiplySequential_300x300() + { + int[][] matrixA = GenerateRandomMatrix(300, 300); + int[][] matrixB = GenerateRandomMatrix(300, 300); + MultiplySequential(matrixA, matrixB); + } + + [Benchmark] + public void MultiplyParallel_300x300_4TH() + { + int[][] matrixA = GenerateRandomMatrix(300, 300); + int[][] matrixB = GenerateRandomMatrix(300, 300); + MultiplyParallel(matrixA, matrixB, 4); + } + [Benchmark] + public void MultiplyParallel_300x300_8TH() + { + int[][] matrixA = GenerateRandomMatrix(300, 300); + int[][] matrixB = GenerateRandomMatrix(300, 300); + MultiplyParallel(matrixA, matrixB, 8); + } + [Benchmark] + public void MultiplyParallel_300x300_16TH() + { + int[][] matrixA = GenerateRandomMatrix(300, 300); + int[][] matrixB = GenerateRandomMatrix(300, 300); + MultiplyParallel(matrixA, matrixB, 16); + } + [Benchmark] + public void MultiplySequential_500x500() + { + int[][] matrixA = GenerateRandomMatrix(500, 500); + int[][] matrixB = GenerateRandomMatrix(500, 500); + MultiplySequential(matrixA, matrixB); + } + + [Benchmark] + public void MultiplyParallel_500x500_4TH() + { + int[][] matrixA = GenerateRandomMatrix(500, 500); + int[][] matrixB = GenerateRandomMatrix(500, 500); + MultiplyParallel(matrixA, matrixB, 4); + } + [Benchmark] + public void MultiplyParallel_500x500_8TH() + { + int[][] matrixA = GenerateRandomMatrix(500, 500); + int[][] matrixB = GenerateRandomMatrix(500, 500); + MultiplyParallel(matrixA, matrixB, 8); + } + [Benchmark] + public void MultiplyParallel_500x500_16TH() + { + int[][] matrixA = GenerateRandomMatrix(500, 500); + int[][] matrixB = GenerateRandomMatrix(500, 500); + MultiplyParallel(matrixA, matrixB, 16); + } + private static int[][] GenerateRandomMatrix(int rows, int cols) + { + int[][] matrix = new int[rows][]; + + Random rand = new Random(); + + for (int i = 0; i < rows; i++) + { + matrix[i] = new int[cols]; + for (int j = 0; j < cols; j++) + { + matrix[i][j] = rand.Next(1, 10); + } + } + + return matrix; + } +} \ No newline at end of file diff --git a/tasks/mutriskov-ds/lab_5/Task/Task.csproj b/tasks/mutriskov-ds/lab_5/Task/Task.csproj new file mode 100644 index 0000000..9a7137b --- /dev/null +++ b/tasks/mutriskov-ds/lab_5/Task/Task.csproj @@ -0,0 +1,14 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + diff --git a/tasks/mutriskov-ds/lab_5/Task/Task.sln b/tasks/mutriskov-ds/lab_5/Task/Task.sln new file mode 100644 index 0000000..8910ba5 --- /dev/null +++ b/tasks/mutriskov-ds/lab_5/Task/Task.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Task", "Task.csproj", "{1757C2C7-9BDF-4A50-9998-93FB49BD9A72}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1757C2C7-9BDF-4A50-9998-93FB49BD9A72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1757C2C7-9BDF-4A50-9998-93FB49BD9A72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1757C2C7-9BDF-4A50-9998-93FB49BD9A72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1757C2C7-9BDF-4A50-9998-93FB49BD9A72}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/tasks/mutriskov-ds/lab_5/images/1.png b/tasks/mutriskov-ds/lab_5/images/1.png new file mode 100644 index 0000000000000000000000000000000000000000..8857612006792ed154fc48581635ef8bd3e39a4a GIT binary patch literal 30250 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 z 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 literal 0 HcmV?d00001