2012-07-27 3 views
0

내 코드에 멀티 스레딩 부분을 추가했습니다.멀티 스레딩 속도 문제

public class ThreadClassSeqGroups 
    { 
     public Dictionary<string, string> seqGroup; 
     public Dictionary<string, List<SearchAlgorithm.CandidateStr>> completeModels; 
     public Dictionary<string, List<SearchAlgorithm.CandidateStr>> partialModels; 
     private Thread nativeThread; 

     public ThreadClassSeqGroups(Dictionary<string, string> seqs) 
     { 
      seqGroup = seqs; 
      completeModels = new Dictionary<string, List<SearchAlgorithm.CandidateStr>>(); 
      partialModels = new Dictionary<string, List<SearchAlgorithm.CandidateStr>>(); 
     } 

     public void Run(DescrStrDetail dsd, DescrStrDetail.SortUnit primarySeedSu, 
      List<ushort> secondarySeedOrder, double partialCutoff) 
     { 
      nativeThread = new Thread(() => this._run(dsd, primarySeedSu, secondarySeedOrder, partialCutoff)); 
      nativeThread.Priority = ThreadPriority.Highest; 
      nativeThread.Start(); 
     } 

     public void _run(DescrStrDetail dsd, DescrStrDetail.SortUnit primarySeedSu, 
      List<ushort> secondarySeedOrder, double partialCutoff) 
     { 
      int groupSize = this.seqGroup.Count; 
      int seqCount = 0; 
      foreach (KeyValuePair<string, string> p in seqGroup) 
      { 
       Console.WriteLine("ThreadID {0} (priority:{1}):\t#{2}/{3} SeqName: {4}", 
        nativeThread.ManagedThreadId, nativeThread.Priority.ToString(), ++seqCount, groupSize, p.Key); 
       List<SearchAlgorithm.CandidateStr> tmpCompleteModels, tmpPartialModels; 
       SearchAlgorithm.SearchInBothDirections(
         p.Value.ToUpper().Replace('T', 'U'), dsd, primarySeedSu, secondarySeedOrder, partialCutoff, 
         out tmpCompleteModels, out tmpPartialModels); 
       completeModels.Add(p.Key, tmpCompleteModels); 
       partialModels.Add(p.Key, tmpPartialModels); 
      } 
     } 

     public void Join() 
     { 
      nativeThread.Join(); 
     } 

    } 

class Program 
{ 
    public static int _paramSeqGroupSize = 2000; 
    static void Main(Dictionary<string, string> rawSeqs) 
    { 
     // Split the whole rawSeqs (Dict<name, seq>) into several groups 
     Dictionary<string, string>[] rawSeqGroups = SplitSeqFasta(rawSeqs, _paramSeqGroupSize); 


     // Create a thread for each seqGroup and run 
     var threadSeqGroups = new MultiThreading.ThreadClassSeqGroups[rawSeqGroups.Length]; 
     for (int i = 0; i < rawSeqGroups.Length; i++) 
     { 
      threadSeqGroups[i] = new MultiThreading.ThreadClassSeqGroups(rawSeqGroups[i]); 
      //threadSeqGroups[i].SetPriority(); 
      threadSeqGroups[i].Run(dsd, primarySeedSu, secondarySeedOrder, _paramPartialCutoff); 
     } 

     // Merge results from threads after the thread finish 
     var allCompleteModels = new Dictionary<string, List<SearchAlgorithm.CandidateStr>>(); 
     var allPartialModels = new Dictionary<string, List<SearchAlgorithm.CandidateStr>>(); 
     foreach (MultiThreading.ThreadClassSeqGroups t in threadSeqGroups) 
     { 
      t.Join(); 
      foreach (string name in t.completeModels.Keys) 
      { 
       allCompleteModels.Add(name, t.completeModels[name]); 
      } 
      foreach (string name in t.partialModels.Keys) 
      { 
       allPartialModels.Add(name, t.partialModels[name]); 
      } 
     } 
    } 
} 

그러나, 다중 스레드 속도가 단일 스레드보다 훨씬 느리다 및 CPU 부하가 일반적 < 10 %이다. 예를 들어

:

입력 파일 2500 문자열

_paramGroupSize = 3000

포함될는 메인 스레드 + 1 계산 스레드

_paramGroupSize = 400 초

200 비용, 메인 쓰레드 + 7 계산 스레드 많은 비용 더 많은 시간 (나는 10 이상의 최소 한도를 달리게하고 난 후에 그것을 죽였다).

구현에 문제가 있습니까? 속도를 높이는 방법?

감사합니다.

+0

'SearchAlgorithm.SearchInBothDirections'의 기능은 무엇입니까? –

+0

DotTrace와 같은 프로파일 러를 사용하면 시간이 소모되는 위치를 알 수 있습니다. –

+0

@ Bryan : SearchAlgorithm.SearchInBothDirections는 주어진 문자열에 대해 집중적 인 검색을 수행하고 candidateStr의 두 목록을 외부 매개 변수로 반환합니다. – Mavershang

답변

0

멀티 스레딩 이전의 코드는 무엇입니까? 이 코드가 무엇을하는지 말하는 것은 어렵습니다. 그리고 많은 "작동하는"코드는 검색 알고리즘에 숨겨져있는 것 같습니다. 그러나 일부 생각 :

  1. 당신은 "입력 파일"을 언급하지만,이 명확하게 코드에 표시되지 않습니다 - 파일 액세스가 스레드되는 경우,이 병목 될 것 파일 액세스와 같은 성능을 향상되지 않습니다.
  2. CPU 코어보다 많은 스레드를 생성하면 궁극적으로 성능이 저하됩니다 (각 스레드가 다른 리소스에서 대기하는 것을 막지 않는 한). 귀하의 경우에는 총 스레드 8 개가 너무 많다는 것을 알려드립니다.
  3. 많은 데이터 (메모리) 액세스가 클래스를 통해 이루어질 수 있으며 이는 Main 메서드의 변수 dsd에서 모든 하위 스레드로 전달됩니다. 그러나이 변수의 선언은 없으므로 사용법/구현은 알 수 없습니다. 이 변수에 여러 스레드가 동시에 액세스하지 못하도록하는 잠금이 있으면 여러 스레드가이 데이터에서 잠겨 잠재적으로 서로 성능이 저하됩니다.
0

스레드가 실행되면 특정 프로세서에서 시간이 제공됩니다. 프로세서보다 많은 스레드가있는 경우 시스템 컨텍스트는 스레드간에 전환하여 모든 활성 스레드를 처리 할 수 ​​있습니다. 문맥 전환은 은 정말 비싸입니다. 프로세서보다 많은 스레드가있는 경우 대부분의 CPU 시간이 컨텍스트 전환으로 인해 처리되어 단일 스레드 솔루션이 멀티 스레드 솔루션보다 더 빨리 으로 표시 될 수 있습니다.

이 예에서는 불확실한 수의 스레드가 시작됨을 보여줍니다. SplitSeqFasta이 코어보다 많은 항목을 반환하면 더 많은 스레드와 코어를 만들고 많은 컨텍스트 전환을 도입합니다.

수동으로 스레드 수를 줄이거 나 스레드 병렬 라이브러리 및 Parallel 클래스와 같은 것을 사용하여 자동으로 스레드를 조절하는 것이 좋습니다.

3

여러 스레드와 병렬로 파일을 처리하려고합니다. 단일 기계 디스크가 있다고 가정 할 때 이것은 나쁜 생각입니다.

기본적으로 디스크의 헤드는 각 읽기 요청에 대해 다음 읽기 위치를 검색해야합니다.이것은 값 비싼 작업이며 여러 스레드가 읽기 명령을 내리기 때문에 각 스레드가 돌아갈 때마다 헤드가 튀어 오르는 것을 의미합니다. 이렇게하면 단일 스레드가 읽기를 수행하는 경우와 비교하여 성능이 크게 저하됩니다.