Как увеличить скорость вычислений 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("Готово");
- }
- }
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д