2012-12-21 1 views
1

모든 프로그래밍 언어에서 Windows 및 Linux의 스레드 (또는 광섬유)에 대한 일반적인 질문이 있습니다.작은 10ms 작업을 평행화할 수 있습니까? (예 : 행렬 반전)

"대기중인 두 번째 스레드"를 가질 수 있으며 신속하게 선제 공격을받지 않고 몇 밀리 초 동안 작은 작업을 수행하도록 도와줍니다. 뮤텍스와 스핀 잠금이없는 읽기 쉬운 코드가 필요하다고 덧붙여 야합니다.

작은 작업에서 기존 스레드 풀이 작동하지 않는다는 것을 나타내려면 C#의 행렬 반전 문제를 고려하십시오. Ivan Kuckir의 matrix class을 사용하고 있습니다. 나는 그의 반전 기능을 복사하고 다음과 같이 InvertParallel 전화 :

다음
public Matrix InvertParallel() // modified from Ivan's Invert(), see link above 
{ 
    if (L == null) MakeLU(); 
    Matrix inv = new Matrix(rows, cols); 
    Parallel.ForEach<int>(Enumerable.Range(0, rows), rowID => 
    { 
     Matrix Ei = Matrix.ZeroMatrix(rows, 1); 
     Ei[rowID, 0] = 1; 
     Matrix col = SolveWith(Ei); 
     inv.SetCol(col, rowID); 
    }); 
    return inv; 
} 

내가 호출 반전과 Invert_Parallel 기능을 모두와 걸리는 시간을 측정 :

static void Main() 
{ 
    Stopwatch sw = new Stopwatch(); sw.Start(); 
    Matrix A = Matrix.IdentityMatrix(50, 50); 
    Matrix I1 = A.Invert(); 
    long elapsed1 = sw.ElapsedMilliseconds; 
    Matrix I2 = A.InvertParallel(); 
    long elapsed2 = sw.ElapsedMilliseconds - elapsed1; 
    Console.WriteLine("Matrix size=" + A.rows + ", Invert=" + elapsed1 + "ms, Invert_Parallel=" + elapsed2 + "ms"); 
} 

상당히 명백한 결과가 보여 그 작은 작업 (행렬 크기 50), 스레드 풀에서 작업을 시작하는 것이 단일 스레드를 실행하는 것보다 느립니다.

Matrix size=50, Invert= 5ms, InvertParallel=21ms 
Matrix size=100, Invert= 19ms, InvertParallel=24ms 
Matrix size=200, Invert=137ms, InvertParallel=44ms 

(사과 - 나는 r 내가 새로운 포스터 인 것처럼 아래 노트에서 모든 링크를 emove)

추신. 관련 S/O 관련 기사 : '동시에 두 개의 스레드를 시작하는 방법', 'Linux - 스레드 및 프로세스 일정 우선 순위'

P.S. 네, O (N^2.376)로 비례하여 역수를 계산하는 더 영리한 알고리즘이 있다는 것을 압니다.

P.P.S. 나는 사용자 모드 스케줄링 (Windows의 UMS)에 익숙하지 않다. User-Mode Scheduling ('UMS' on Windows), 도움이 될까요?

+3

"할 수 있어요."- 확실히. "해야할까요?"좋은 질문입니다. –

답변

1

스레드간에 작업을 전달할 때 특히 스레드와 관련된 많은 양의 데이터가있는 경우 오버 헤드가 적어 작은 작업에서는 성능이 저하 될 수 있습니다. 하나 이상의 코어를 사용하는 것이 더 빠른 곳에서 달콤한 자리를 찾아야합니다.

BTW 작업자 스레드 중 하나를 만들고 현재 스레드가 하나의 컨텍스트 스위치를 저장하고 캐시간에 복사본을 만들어 약간의 향상을 얻을 수 있습니다. 예 : 코어가 8 개인 경우 1/7에서 7 개의 다른 스레드를 전달하고 현재 스레드에서 1/8을 수행합니다.

+0

Peter - 문제가 어디 있는지 설명해 주시겠습니까? 5ms는 나에게 매우 긴 시간으로 보입니다. 컨텍스트 스위치와 같은 것보다 훨씬 오래 걸립니다. 이 경우 수영장이 왜 그렇게 느린가? 21-5 = 16ms 동안 무엇을하고 있습니까? C#에서 행렬 객체를 대기열에 올려 놓는 것은 참조 푸시 일뿐입니다. 여기서 무슨 일이 일어나고있는거야? 왜 반전은 그렇게 비효율적입니까? –

+0

참조 푸시와 컨텍스트 전환 (스레드 깨우기)은 Java에서 약 10 마이크로 초입니다 (C#에서는 거의 동일합니다). 한 캐시에서 다른 캐시로 데이터를 밀어 넣는 것은 충분한 활동이있는 경우 밀리 초가 걸릴 수 있습니다. –

+0

피터는 정확했다. 두 번째 스레드를 깨우는 것은 매우 빠릅니다. 위의 코드에서 문제는 스레드 풀을 준비하지 않은 것입니다. 스레드 풀을 프라임하면 다음 결과를 얻습니다.'Matrix size = 50, Invert = 5ms, Invert_Parallel = 2ms' – mlnolectric