2014-09-16 2 views
0

У меня есть объект Item с свойством, называемым generator_list (hashset строк). У меня есть 8000 объектов, и для каждого объекта я хотел бы посмотреть, как это generator_list пересекается со всеми остальными generator_list, а затем я хотел бы сохранить номер пересечения в List<int>, который будет иметь 8000 элементов, логически.Параллельный цикл в C#, доступ к той же переменной

Процесс занимает около 8 минут, но всего несколько минут с параллельной обработкой, но я не думаю, что делаю параллельную часть вправо, следовательно, вопрос. Может кто-нибудь скажет мне, если и как мне нужно изменить свой код, чтобы воспользоваться параллельными циклами?

Код для моего Item объекта:

public class Item 
{ 
    public int index { get; set; } 
    public HashSet<string> generator_list = new HashSet<string>(); 
} 

Я сохранил все свои объекты элемент в List<Item> items (8000 элементов). Я создал метод, который принимает в пунктах (список, я хочу, чтобы сравнить) и 1 пункт (то, что я хочу, чтобы сравнить), и это так:

public void Relatedness2(List<Item> compare, Item compare_to) 
     { 
      int compare_to_length = compare_to.generator_list.Count; 
      foreach (Item block in compare) 
      { 
       int block_length = block.generator_list.Count; 
       int both = 0; //this counts the intersection number 
       if (compare_to_length < block_length) //to make sure I'm looping 
                 //over the smaller set 
       { 
        foreach (string word in compare_to.generator_list) 
        { 
         if (block.generator_list.Contains(word)) 
         { 
          both = both + 1; 
         } 
        } 
       } 
       else 
       { 
        foreach (string word in block.generator_list) 
        { 
         if (compare_to.generator_list.Contains(word)) 
         { 
          both = both + 1; 
         } 
        } 
       } 
        // I'd like to store the intersection number, both, 
        // somewhere so I can effectively use parallel loops 
      } 

     } 

И, наконец, мой параллельный forloop является:

Parallel.ForEach(items, (kk, state, index) => Relatedness2(items, kk)); 

Любые предложения?

+0

Что происходит, когда вы запускаете его? –

+0

Вы должны изучить использование параллельного объекта коллекции, такого как этот [ConcurrentDictionary (Of TKey, TValue)] (http://msdn.microsoft.com/en-us/library/dd287191 (v = vs.110). aspx), если вы не хотите реализовать его самостоятельно. См. Также: [Параллельный HashSet в .NET Framework] (http://stackoverflow.com/questions/18922985/concurrent-hashsett-in-net-framework). – Neolisk

+0

Привет, когда я на самом деле запускаю его, он работает, и я использовал для хранения списка результатов для каждого элемента в свойстве для этого элемента. – thatandrey

ответ

2

Может быть что-то вроде этого

public Dictionary<int, int> Relatedness2(IList<Item> compare, Item compare_to) 
     { 
      int compare_to_length = compare_to.generator_list.Count; 
      var intersectionData = new Dictionary<int, int>(); 
      foreach (Item block in compare) 
      { 
       int block_length = block.generator_list.Count; 
       int both = 0; 
       if (compare_to_length < block_length) 
       { 
        foreach (string word in compare_to.generator_list) 
        { 
         if (block.generator_list.Contains(word)) 
         { 
          both = both + 1; 
         } 
        } 
       } 
       else 
       { 
        foreach (string word in block.generator_list) 
        { 
         if (compare_to.generator_list.Contains(word)) 
         { 
          both = both + 1; 
         } 
        } 
       } 
       intersectionData[block.index] = both; 
      } 
      return intersectionData; 
     } 

И

  List<Item> items = new List<Item>(8000); 
     //add to list 
     var dictionary = new ConcurrentDictionary<int, Dictionary<int, int>>();//thread-safe dictionary 

     var readOnlyItems = items.AsReadOnly();// if you sure you wouldn't modify collection, feel free use items directly 
     Parallel.ForEach(readOnlyItems, item => 
     { 
      dictionary[item.index] = Relatedness2(readOnlyItems, item); 
     }); 

Я предположил, что индекс уникальным.

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

var intesectiondata = dictionary[1]//dictionary of intersection for item with index 1 

var countOfintersectionItemIndex1AndItemIndex3 = dictionary[1][3] 
var countOfintersectionItemIndex3AndItemIndex7 = dictionary[3][7] 

не забывайте о возможности словаре [я] == NULL

+0

Спасибо, я попробую это. Мой единственный вопрос - это то, что для каждого элемента, поскольку он пересекается с каждым другим элементом, я хотел бы сохранить все результаты в одном списке для каждого элемента. Таким образом, это будет выглядеть как 7, {23,34,0,0,45,100 ....}, и это будет означать, что пункт 7 (основанный на уникальном индексе) имеет пересечение 23 с пунктом 0, 34 с пунктом 1, ... и так далее. Знаете ли вы, как я могу изменить свой код для его реализации? – thatandrey

+0

Ой, подождите, я только что запустил код, и это было BLIZING быстро. Я попытаюсь подтвердить результаты, и я думаю, что ваш словарь действительно дает мне значения, которые я хочу, я просто не понял ваш код. Извините, я только начал программировать этим летом! – thatandrey

+0

Как вы думаете, вы можете обновить свой ответ и добавить этот код? Я не могу следовать за этим, что хорошо в комментариях :( – thatandrey

0

Целесообразные коллекции, вероятно, являются тем, что вы ищете http://msdn.microsoft.com/en-us/library/dd997305(v=vs.110).aspx.

При работе в многопоточной среде, необходимо убедиться, что вы не манипулирования общих данных, в то же время без синхронизации доступа.

.NET Framework предлагает некоторые классы коллекций, которые создаются специально для использования в параллельных средах, что есть у вас , когда вы используете многопоточность. Эти коллекции являются потокобезопасными, что означает, что они внутренне используют синхронизацию до , убедитесь, что к ним можно получить доступ несколькими потоками при том же времени.

Источник: Программирование на экзамене C# 70-483, Цель 1.1: Реализация multhitreading и асинхронная обработка, используя Одновременные коллекции

Какие следующие коллекции

  • BlockingCollection<T>
  • ConcurrentBag<T>
  • ConcurrentDictionary<T>
  • ConcurentQueue<T>
  • ConcurentStack<T>
+1

Отсутствует подробная информация/пояснения. – Mephy

+1

Спасибо, но поскольку я только начал программировать этим летом, эта информация летает над моей головой. Но я думаю, что я понял, тем более, что один из ответов использовал параллельный словарь, и он начинает пролить свет на всю тему. – thatandrey

0

Если индекс вашего предмета смежный и начинается с нуля, вам не нужен класс предметов вообще. Просто используйте Список < HashSet < < string >>, он позаботится об индексах для вас. Это решение находит количество пересечений между 1 элементом и другими в параллельном LINQ. Затем он берет это и запускает его во всех элементах вашей коллекции в другом параллельном LINQ. Например,

var items = new List<HashSet<string>> 
{ 
    new HashSet<string> {"1", "2"}, 
    new HashSet<string> {"2", "3"}, 
    new HashSet<string> {"3", "4"}, 
    new HashSet<string>{"1", "4"} 
}; 


var intersects = items.AsParallel().Select( //Outer loop to run on all items 
    item => items.AsParallel().Select(   //Inner loop to calculate intersects 
      item2 => item.Intersect(item2).Count()) 
      //This ToList will create a single List<int> 
      //with the intersects for that item 
      .ToList() 
     //This ToList will create the final List<List<int>> 
     //that contains all intersects. 
     ).ToList(); 
+0

Спасибо, я обязательно попробую это тоже! У меня был только шанс попробовать другой код ответа, и у меня есть классы в течение всего дня, но как только я буду свободен, я также попытаюсь это реализовать. – thatandrey

+0

Привет, мне любопытно, в чем смысл 'newItem'? Я понимаю элементы, и я хотел бы продолжить и попробовать это, но у меня нет эквивалента 'newItem' в моем коде? – thatandrey

+0

@ user3408097 Возможно, я не понимаю ваш код. Я думал, что вы хотите сравнить один элемент с вашим списком элементов и получить количество пересечений для каждого существующего элемента в списке по сравнению с этим новым элементом. Похоже, вы уже нашли свой ответ. –