C\#병렬 및 다 중 스 레 드 프로 그래 밍-병렬 집합 과 PLinq

4.567915.우 리 는 Parallel 의 용법 을 배 웠 다.병렬 프로 그래 밍 은 본질 적 으로 다 중 스 레 드 의 프로 그래 밍 이다.그러면 여러 스 레 드 가 하나의 임 무 를 동시에 처리 할 때 반드시 자원 방문 문제 와 이른바 스 레 드 안전 이 발생 할 것 이다.현실 에서 우리 가 개발 한 프로젝트 는 하나의 병행 적 인 예 로 서로 다른 모듈 을 다른 사람 에 게 나 누 어 동시에 진행 해 야 짧 은 시간 안에 큰 프로젝트 를 할 수 있다.모두 가 자신의 코드 만 쓰 고 다 쓴 후에 합 쳐 지지 않 는 다 는 것 을 알 게 된다 면 이런 병행 은 의미 가 없다.
병렬 산법 의 등장 에 따라 발생 하 는 것 도 병렬 집합 과 스 레 드 안전 집합 이 있다.마이크로소프트 방향 도 주도면밀 하고 링크 를 잊 지 않 았 으 며 링크 의 병렬 버 전,plinq-Parallel Linq 를 출시 했다. 
1.병렬 집합―스 레 드 안전 집합
병렬 컴 퓨 팅 에 사용 되 는 여러 스 레 드 를 동시에 계산 하기 때문에 모든 스 레 드 가 자원 에 대한 접근 을 제어 해 야 합 니 다.우 리 는 평소에 자주 사용 하 는 List집합 을 살 펴 보고 병렬 컴 퓨 팅 에서 의 표현 을 살 펴 보 겠 습 니 다.콘 솔 프로그램 을 새로 만 들 고 PEnumerable 류 를 추가 합 니 다.(물론 당신 도 main 방법 에 직접 써 서 테스트 하고 따로 쓰 는 것 을 권장 합 니 다)다음 과 같은 방법 을 쓰 십시오.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;

namespace ThreadPool
{
 public class PEnumerable
 {
  public static void ListWithParallel()
  {
   List<int> list = new List<int>();
   Parallel.For(0, 10000, item =>
   {
   list.Add(item);
   });
   Console.WriteLine("List's count is {0}",list.Count());
  }
 }
}
F5 실행 을 누 르 면 다음 결 과 를 얻 을 수 있 습 니 다:

결과 에 나타 난 5851 을 보 았 지만 우 리 는 10000 번 을 순환 했다!왜 결과 가 틀 렸 지?이것 은 List가 비 스 레 드 안전 집합 이기 때 문 입 니 다.모든 스 레 드 가 그의 값 을 수정 할 수 있다 는 뜻 입 니 다.
다음은 병렬 집합-스 레 드 안전 집합 을 살 펴 보 겠 습 니 다.System.collections.Concurrent 네 임 스페이스 에서 먼저 ConcurrentBag팬 집합 을 살 펴 보 겠 습 니 다.그 용법 은 List와 유사 합 니 다.먼저 방법 을 써 서 테스트 해 보 겠 습 니 다.

public static void ConcurrentBagWithPallel()
  {
   ConcurrentBag<int> list = new ConcurrentBag<int>();
   Parallel.For(0, 10000, item =>
   {
   list.Add(item);
   });
   Console.WriteLine("ConcurrentBag's count is {0}", list.Count());
  }
두 가지 방법 을 동시에 실행 한 결 과 는 다음 과 같다.

컨 커 런 트 백 집합 결과 가 정확 하 다 는 것 을 알 수 있다.다음은 코드 를 수정 하여 ConcurrentBag 안의 데 이 터 를 어떻게 저장 하 는 지 보 겠 습 니 다.코드 를 수정 하면 다음 과 같 습 니 다.

public static void ConcurrentBagWithPallel()
  {
   ConcurrentBag<int> list = new ConcurrentBag<int>();
   Parallel.For(0, 10000, item =>
   {
   list.Add(item);
   });
   Console.WriteLine("ConcurrentBag's count is {0}", list.Count());
   int n = 0;
   foreach(int i in list)
   {
   if (n > 10)
    break;
   n++;
   Console.WriteLine("Item[{0}] = {1}",n,i);
   }
   Console.WriteLine("ConcurrentBag's max item is {0}", list.Max());

  }
먼저 실행 결 과 를 살 펴 보 겠 습 니 다.

이 를 통 해 알 수 있 듯 이 ConcurrentBag 의 데 이 터 는 순서대로 배열 되 어 있 지 않 고 순서 가 어 지 럽 고 무 작위 적 이다.우리 가 평소에 사용 하 는 Max,First,Last 등 linq 방법 은 모두 있다.그 시 기 는 Enumerable 과 유사 한 용법 이 므 로 마이크로소프트 의 MSDN 을 참고 하여 구체 적 인 용법 을 알 수 있다.
스 레 드 안전 에 관 한 집합 은 아직도 많 습 니 다.우리 가 평소에 사용 하 는 집합 과 차이 가 많 지 않 습 니 다.예 를 들 어 Dictionary 와 유사 한 Concurrent Dictionary,그리고 Concurrent Stack,ConcurrentQueue 등 이 있 습 니 다.
2.Parallel Linq 의 용법 및 성능
1、AsParallel
앞서 병행 하 는 For 와 foreach 에 대해 알 아 봤 는데,오늘 은 Linq 의 병행 버 전이 어떤 지 볼 까요?테스트 를 위해 사용자 정의 클래스 를 추가 합 니 다.코드 는 다음 과 같 습 니 다.

public class Custom
 {
  public string Name { get; set; }
  public int Age { get; set; }
  public string Address { get; set; }
 }
 다음 테스트 코드 를 쓰 십시오:

public static void TestPLinq()
  {
   Stopwatch sw = new Stopwatch();
   List<Custom> customs = new List<Custom>();
   for (int i = 0; i < 2000000; i++)
   {
   customs.Add(new Custom() { Name = "Jack", Age = 21, Address = "NewYork" });
   customs.Add(new Custom() { Name = "Jime", Age = 26, Address = "China" });
   customs.Add(new Custom() { Name = "Tina", Age = 29, Address = "ShangHai" });
   customs.Add(new Custom() { Name = "Luo", Age = 30, Address = "Beijing" });
   customs.Add(new Custom() { Name = "Wang", Age = 60, Address = "Guangdong" });
   customs.Add(new Custom() { Name = "Feng", Age = 25, Address = "YunNan" });
   }

   sw.Start();
   var result = customs.Where<Custom>(c => c.Age > 26).ToList();
   sw.Stop();
   Console.WriteLine("Linq time is {0}.",sw.ElapsedMilliseconds);

   sw.Restart();
   sw.Start();
   var result2 = customs.AsParallel().Where<Custom>(c => c.Age > 26).ToList();
   sw.Stop();
   Console.WriteLine("Parallel Linq time is {0}.", sw.ElapsedMilliseconds);
  }
사실은 AsParallel()방법 을 추가 한 것 입 니 다.다음은 실행 결 과 를 보 겠 습 니 다.

시간 이 배로 차이 가 났 지만 가끔 은 이렇게 차이 가 나 지 않 을 때 가 있 습 니 다.시스템 의 현재 자원 이 용 률 을 봐 야 합 니 다.많이 테스트 해 보 세 요.
사실,AsParallel()이 방법 은 List집합 을 포함 하여 모든 집합 과 응용 하여 조회 속도 와 시스템 성능 을 향상 시 킬 수 있 습 니 다.
2,GroupBy 방법
프로젝트 에서 우 리 는 항상 데 이 터 를 처리 해 야 합 니 다.예 를 들 어 조별 통 계 를 통 해 우 리 는 linq 에서 도 실현 할 수 있다 는 것 을 알 고 있 습 니 다.오늘 은 새로운 ToLookup 방법 을 배우 고 테스트 방법 을 쓰 겠 습 니 다.코드 는 다음 과 같 습 니 다.

public static void OrderByTest()
  {
   Stopwatch stopWatch = new Stopwatch();
   List<Custom> customs = new List<Custom>();
   for (int i = 0; i < 2000000; i++)
   {
   customs.Add(new Custom() { Name = "Jack", Age = 21, Address = "NewYork" });
   customs.Add(new Custom() { Name = "Jime", Age = 26, Address = "China" });
   customs.Add(new Custom() { Name = "Tina", Age = 29, Address = "ShangHai" });
   customs.Add(new Custom() { Name = "Luo", Age = 30, Address = "Beijing" });
   customs.Add(new Custom() { Name = "Wang", Age = 60, Address = "Guangdong" });
   customs.Add(new Custom() { Name = "Feng", Age = 25, Address = "YunNan" });
   }

   stopWatch.Restart();
   var groupByAge = customs.GroupBy(item => item.Age).ToList();
   foreach (var item in groupByAge)
   {
   Console.WriteLine("Age={0},count = {1}", item.Key, item.Count());
   }
   stopWatch.Stop();

   Console.WriteLine("Linq group by time is: " + stopWatch.ElapsedMilliseconds);


   stopWatch.Restart();
   var lookupList = customs.ToLookup(i => i.Age);
   foreach (var item in lookupList)
   {
   Console.WriteLine("LookUP:Age={0},count = {1}", item.Key, item.Count());
   }
   stopWatch.Stop();
   Console.WriteLine("LookUp group by time is: " + stopWatch.ElapsedMilliseconds);
  }
실행 결 과 는 다음 과 같 습 니 다.

ToLookup 방법 은 집합 을 읽 기 전용 집합 으로 바 꾸 는 것 이기 때문에 빅 데 이 터 를 그룹 으로 나 눌 때 List 보다 성능 이 좋 습 니 다.관련 자 료 를 찾 아 볼 수 있 습 니 다.여 기 는 지면 문제 로 더 이상 자세히 말 하지 않 습 니 다.
이상 은 C\#병렬 및 다 중 스 레 드 프로 그래 밍-병렬 집합 과 PLinq 의 상세 한 내용 입 니 다.C\#병렬 및 다 중 스 레 드 프로 그래 밍 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기