Как увеличить скорость вычислений 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("Готово");
        }
    }
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

13   голосов , оценка 4.385 из 5
Похожие ответы