Как увеличить скорость вычислений 500 000 строк? - C#
Формулировка задачи:
Здравствуйте. Вопрос к людям с опытом. Как ускорить вычисления 500 000 строк. Задача посчитать, какую прибыль приносил магазин в среднем в день за месяц, т.е сумма прибыли за месяц / кол-во дней когда магазин работал. Имеется 600 магазинов, по которым получается список из более 20 000 строк (магазин, год, месяц), с продажами за день получается список из 500 000 строк (магазин, год, месяц, день, продажи).
Результаты применение распараллеливания расчётов, оказались неудовлетворительным прирост в скорости на 30 сек. С 1600 сек (без многопоточности) до 1570 сек (многопоточность). А неудовлетворительны потому, что в ексэле такая операция при построении сводной таблицы занимает секунды. Вот и вопрос "Как ускорить вычисление?".
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Threading; using System.Threading.Tasks; namespace PohojMagaz { class Magazin : IEquatable<Magazin> { public Magazin(){} public Magazin(string NameStore, ushort Year, byte Month, DateTime dataTime, double SalesRub) { this.NameStore = NameStore; this.Year = Year; this.Month = Month; this.dataTime = dataTime; this.SalesRub = SalesRub; } public string NameStore { get; set; } public ushort Year { get; set; } public byte Month { get; set; } public DateTime dataTime = new DateTime(); public double SalesRub { get; set; } public bool Equals(Magazin other) { //Check whether the compared object is null. if (Object.ReferenceEquals(other, null)) return false; //Check whether the compared object references the same data. if (Object.ReferenceEquals(this, other)) return true; //Check whether the products' properties are equal. return NameStore.Equals(other.NameStore) && Year.Equals(other.Year) && Month.Equals(other.Month) && dataTime.Equals(other.dataTime) && SalesRub.Equals(other.SalesRub); } // If Equals() returns true for a pair of objects // then GetHashCode() must return the same value for these objects. public override int GetHashCode() { //Get hash code for the Name field if it is not null. int hashMagazinNameStore = NameStore == null ? 0 : NameStore.GetHashCode(); //Get hash code for the Code field. int hasMagazinYear = Year.GetHashCode(); int hasMagazinMonth = Month.GetHashCode(); int hasMagazindataTime = dataTime.GetHashCode(); int hasMagazindataSalesRub = SalesRub.GetHashCode(); //Calculate the hash code for the product. return hasMagazinYear ^ hashMagazinNameStore ^ hasMagazinMonth ^ hasMagazindataTime ^ hasMagazindataSalesRub; } } class Program { static void Main(string[] args) { Console.WriteLine("Чтение файла"); List<Magazin> fail = new List<Magazin>(); using (var str = new StreamReader("1.txt", Encoding.UTF8)) { string s; int z = 0; while ((s = str.ReadLine()) != null) { z++; if (z > 1) { string[] sPod = s.Split('\t'); fail.Add(new Magazin()); fail.Last().NameStore = sPod[0]; fail.Last().Year = Convert.ToUInt16(sPod[1]); fail.Last().Month = Convert.ToByte(sPod[2]); fail.Last().dataTime = Convert.ToDateTime(sPod[3]); fail.Last().SalesRub = sPod[4] == "" ? 0 : Convert.ToDouble(sPod[4].Replace(',','.')); } } } // Получаем список магазинов для анализа List<string> nameStore = fail.Select(r => r.NameStore).Distinct().ToList(); List<ushort> year = fail.Select(r => r.Year).Distinct().ToList(); List<byte> month = fail.Select(r => r.Month).Distinct().ToList(); Console.WriteLine("Убрать повторяющиеся"); //Оставить уникальные значение (магазин, год, месяц) List<Magazin> storeAvgDey = new List<Magazin>(); storeAvgDey = fail.AsParallel().Select(r => new Magazin(r.NameStore, r.Year, r.Month, new DateTime(), 0)).Distinct().ToList(); //Рассчитываем какую прибыль приносил магазин, в среднем, в день за месяц Console.WriteLine("Расчёт среднего магазина"); Parallel.ForEach(storeAvgDey, M => { M.SalesRub = fail.AsParallel().Where( w => w.NameStore == M.NameStore & w.Month == M.Month & w.Year == M.Year).Select( r => r.SalesRub).Average(); }); //Console.WriteLine("Поиск похожих магазинов"); //Console.WriteLine("Вывод в файл"); //using (var stream = new StreamWriter("Результат.txt")) //{ //} Console.WriteLine("Готово"); } } }
Решение задачи: «Как увеличить скорость вычислений 500 000 строк?»
textual
Листинг программы
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Threading; using System.Threading.Tasks; namespace PohojMagaz { //Ключ пользовательского типа данных(несколько ключей Dictionary) class Magazin : IEquatable<Magazin> { public Magazin(){} public Magazin(string NameStore, ushort Year, byte Month) { this.NameStore = NameStore; this.Year = Year; this.Month = Month; } public string NameStore { get; set; } public ushort Year { get; set; } public byte Month { get; set; } public bool Equals(Magazin other) { //Check whether the compared object is null. if (Object.ReferenceEquals(other, null)) return false; //Check whether the compared object references the same data. if (Object.ReferenceEquals(this, other)) return true; //Check whether the products' properties are equal. return NameStore.Equals(other.NameStore) && Year.Equals(other.Year) && Month.Equals(other.Month); } // If Equals() returns true for a pair of objects // then GetHashCode() must return the same value for these objects. public override int GetHashCode() { //Get hash code for the Name field if it is not null. int hashMagazinNameStore = NameStore == null ? 0 : NameStore.GetHashCode(); //Get hash code for the Code field. int hasMagazinYear = Year.GetHashCode(); int hasMagazinMonth = Month.GetHashCode(); //Calculate the hash code for the product. return hasMagazinYear ^ hashMagazinNameStore ^ hasMagazinMonth; } } class Program { static void Main(string[] args) { Console.WriteLine("Чтение файла"); Dictionary<Magazin,List<double>> fail = new Dictionary<Magazin, List<double>>(); using (var str = new StreamReader("1.txt", Encoding.UTF8)) { string s; int z = 0; while ((s = str.ReadLine()) != null) { z++; if (z > 1) { string[] sPod = s.Split('\t'); Magazin temp = new Magazin(sPod[0], Convert.ToUInt16(sPod[1]), Convert.ToByte(sPod[2])); //Проверяем есть ли магазин из потока, если нет, то создаём магазин с List'ом if (!fail.Keys.Contains(temp)) { fail.Add( temp, new List<double>()); fail[temp].Add(sPod[4] == "" ? 0 : Convert.ToDouble(sPod[4])); } else fail[temp].Add(sPod[4] == "" ? 0 : Convert.ToDouble(sPod[4])); } } } //Convert.ToDouble(sPod[4].Replace(',', '.') // Считаем средние продажи в день Dictionary<Magazin, double> storeAvgDey = new Dictionary<Magazin, double>(); Console.WriteLine("Расчёт среднего магазина"); //При использовании параллельного ForEach происходит ошибка "Индекс находился вне границ массива." //Parallel.ForEach(fail, M => // { // storeAvgDey[M.Key] = M.Value.Average(); // }); foreach (var M in fail) { storeAvgDey[M.Key] = M.Value.Average(); } Console.WriteLine("Поиск похожих магазинов"); //Console.WriteLine("Вывод в файл"); //using (var stream = new StreamWriter("Результат.txt")) //{ //} Console.WriteLine("Готово"); } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д