Ускорьте поиск и вставьте в параллельную сумку c #

1

У меня проблема с медленным "построением" списка, и у меня нет идеи, как его ускорить. Вот мой код:

    private static ConcurrentBag<Classe<PojedynczeSlowa>> categoryClasses = new ConcurrentBag<Classe<PojedynczeSlowa>>();
    private const int howManyStudents = 20;
    private static int howManyClasses;
    private static EventWaitHandle[] ewhClass;
    private static List<Classe<Words>> deserializeClasses; 
//...
    public static void CreateCategoryClasses()
    {
        deserializeClasses  = Deserialize();
        howManyClasses = deserializeClasses.Count;
        ewhClass = new EventWaitHandle[howManyClasses];
        for (var i = 4; i >= 0; --i)
        {
            categoryClasses.Add(new Classe<PojedynczeSlowa>(((Categories) i).ToString()));
        }
        WaitCallback threadMethod = ParseCategories;
        ThreadPool.SetMaxThreads(howManyStudents, howManyClasses);

        for (var i = 0; i < howManyClasses; ++i)
        {
            ewhClass[i] = new EventWaitHandle(false, EventResetMode.AutoReset);
            ThreadPool.QueueUserWorkItem(threadMethod, i);
        }
        for (var i = 0; i < howManyClasses; ++i)
        {
            ewhClass[i].WaitOne();
        }

        var xmls = new XmlSerializer(typeof(List<Classe<PojedynczeSlowa>>)); //poprawić!!
        using (var sw = new StreamWriter(@"categoryClasses.xml"))
        {
            xmls.Serialize(sw, categoryClasses.ToList());
        }
    }

    private static void ParseCategories(object index)
    {
        int sum;
        var i = index as int?;

        if (deserializeClasses[i.Value].Category == Categories.PEOPLE.ToString())
        {
            foreach (var word in deserializeClasses[i.Value].Bag)
            {
                sum =
                    deserializeClasses.Count(
                        clas =>
                            clas.Bag.Where(x => clas.Category == deserializeClasses[i.Value].Category)
                                .Contains(word));
                if (!categoryClasses.ElementAt(0).Bag.Contains(new PojedynczeSlowa(word.Word, sum)))
                {
                    categoryClasses.ElementAt(0)
                        .Bag.Add(new PojedynczeSlowa(word.Word,
                            Convert.ToDouble(sum)/
                            Convert.ToDouble(deserializeClasses.Count(x => x.Category == deserializeClasses[i.Value].Category))));
                }
            }
        }
//rest of the code which adds elements to the list on other indexes.
        ewhClass[(i).Value].Set();
    }

Я мог бы добавить, что:

deserializeClasses содержит около 18550 элементов класса "Слово",

и любой из этих элементов ("Word") содержит список строк и int, средний размер этого списка составляет около 200-250 элементов. Я использую.net 4.5.1 Спасибо за помощь!

Теги:
performance
list
multithreading
concurrency

1 ответ

1

Пара вещей (у меня недостаточно комментариев, чтобы комментировать, поэтому мои комментарии здесь тоже)...

1) Определения классов будут очень полезными. Например, у вас есть
if (!categoryClasses.ElementAt(0).Bag.Contains(new PojedynczeSlowa(word.Word, sum)))
который никогда не будет прав, если вы не переопределили object.Equals (не так ли?). Кроме того, гораздо труднее узнать, что происходит с неполным образцом.
2) Ваш код
sum = deserializeClasses.Count(clas => clas.Bag.Where(x => clas.Category == deserializeClasses[i.Value].Category).Contains(word));
вообще не использует x. Рассматривать
sum = deserializeClasses.Count(clas => clas.Category == deserializeClasses[i.Value].Category && clas.Bag.Contains(word));
Это позволяет избежать большого количества потенциальных перерасчетов и может ускорить среднюю стоимость, даже несмотря на то, что стоимость наихудшего случая остается неизменной.
3) Словари - ваш друг. Подумайте о том, чтобы сделать некоторые временные словари, индексированные тем, что вы проверяете. Мне сложно определить, что именно вы пытаетесь сделать (см. Комментарий 1), но я предполагаю, что вы могли бы сэкономить немало стоимости исполнения, в частности вызов Contains(), используя словарь.
4) Я не уверен, что многопоточность поможет вам сэкономить. Я предполагаю, что это замедлит работу, так как это выглядит как CPU, и вы добавляете накладные расходы процессора с переключением потоков.

Я бы помог с некоторым кодом, но я немного тороплюсь и не успеваю догадаться о остальном недостающем коде, чтобы получить все, чтобы скомпилировать.

  • 1
    1. Я отменяю Равные. 2. Да я тоже это вижу и уже исправлю. 3. Да, я изменяю свой код и сначала добавляю слова в ConcurrentDic без какого-либо конкретного «числа», а затем, когда у меня есть словарь со словами, которые мне нужны, я запускаю «алгоритм», но он все еще слишком медленный. В любом случае, спасибо! Я продолжу улучшать это, и позже отправлю то, что я получил.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню