문제

이 코드가 주어진다 :

var arrayStrings = new string[1000];
Parallel.ForEach<string>(arrayStrings, someString =>
{
    DoSomething(someString);
});

1000 개의 스레드가 모두 거의 동시에 생길까요?

도움이 되었습니까?

해결책

아니오, 1000 스레드가 시작되지 않습니다. 예, 얼마나 많은 스레드가 사용되는지 제한합니다. 병렬 확장은 당신이 물리적으로 얼마나 많은지에 따라 적절한 수의 코어를 사용합니다. 그리고 얼마나 많은 사람들이 이미 바쁘다. 각 코어에 대해 작업을 할당 한 다음이라는 기술을 사용합니다. 일을 훔치기 각 스레드가 자체 대기열을 효율적으로 처리하고 실제로 필요할 때 고가의 크로스 스레드 액세스 만 수행하면됩니다.

살펴보십시오 PFX 팀 블로그 ~을 위한 잔뜩 그것이 어떻게 작동하는지에 대한 정보와 모든 종류의 다른 주제.

경우에 따라 원하는 병렬성의 정도를 지정할 수도 있습니다.

다른 팁

단일 코어 머신 ... Parallel.foreach Partitions (청크)에서는 여러 스레드 사이에서 작동하는 컬렉션의 파티션 (청크)이지만 해당 숫자는 고려하고 지속적으로 수행 한 작업을 모니터링하는 알고리즘을 기반으로 계산됩니다. 스레드는 foreach에 할당됩니다. 그래서 Foreach의 본문 부분이 스레드를 대기하는 장기 IO-bound/blocking functions로 전화를 걸면 알고리즘은 더 많은 스레드를 생성하고 그들 사이의 컬렉션을 다시 구분합니다.. 스레드가 빠르게 완료되고 예를 들어 IO 스레드에서 차단하지 않으면 단순히 일부 숫자를 계산하는 것과 같이 알고리즘은 알고리즘이 처리량에 대한 최적을 고려하는 지점으로 스레드 수가 증가 (또는 실제로 다운)됩니다 (각 반복의 평균 완료 시간)..

기본적으로 모든 다양한 병렬 라이브러리 기능 뒤에있는 스레드 풀은 사용할 최적의 스레드 수를 사용합니다. 물리적 프로세서 코어의 수는 방정식의 일부만 형성합니다. 코어 수와 스파이 된 스레드 수 사이에는 단순한 관계가 없습니다.

나는 동기화 스레드의 취소 및 처리에 관한 문서를 찾지 못한다. MS가 MSDN에서 더 나은 예를 제공 할 수 있기를 바랍니다.

본문 코드는 여러 스레드에서 실행되도록 작성해야하며 모든 일반적인 스레드 안전 고려 사항과 함께 프레임 워크가 해당 요소를 초록하지 않습니다.

프로세서/코어 수를 기반으로 최적의 스레드 수를 작동시킵니다. 그들은 모두 한 번에 스폰되지 않습니다.

보다 반복 당 하나의 작업을 사용하기 위해 병렬? "정신 모델"이라는 아이디어를 사용합니다. 그러나 저자는 "하루가 끝나면 구현 세부 사항이 언제든지 변경 될 수 있음을 기억하는 것이 중요하다"고 밝혔다.

좋은 질문. 예에서는 쿼드 코어 프로세서에서도 병렬화 수준이 상당히 낮지 만 일부는 대기하면 병렬화 수준이 상당히 높아질 수 있습니다.

// Max concurrency: 5
[Test]
public void Memory_Operations()
{
    ConcurrentBag<int> monitor = new ConcurrentBag<int>();
    ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
    var arrayStrings = new string[1000];
    Parallel.ForEach<string>(arrayStrings, someString =>
    {
        monitor.Add(monitor.Count);
        monitor.TryTake(out int result);
        monitorOut.Add(result);
    });

    Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}

이제 대기 작업이 추가되어 HTTP 요청을 시뮬레이션 할 때 어떻게되는지 살펴보십시오.

// Max concurrency: 34
[Test]
public void Waiting_Operations()
{
    ConcurrentBag<int> monitor = new ConcurrentBag<int>();
    ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
    var arrayStrings = new string[1000];
    Parallel.ForEach<string>(arrayStrings, someString =>
    {
        monitor.Add(monitor.Count);

        System.Threading.Thread.Sleep(1000);

        monitor.TryTake(out int result);
        monitorOut.Add(result);
    });

    Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}

나는 아직 아무런 변화도하지 않았고 동시성/병렬화 수준이 드라마 적으로 점프되었습니다. 동시성은 한계가 높아질 수 있습니다 ParallelOptions.MaxDegreeOfParallelism.

// Max concurrency: 43
[Test]
public void Test()
{
    ConcurrentBag<int> monitor = new ConcurrentBag<int>();
    ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
    var arrayStrings = new string[1000];
    var options = new ParallelOptions {MaxDegreeOfParallelism = int.MaxValue};
    Parallel.ForEach<string>(arrayStrings, options, someString =>
    {
        monitor.Add(monitor.Count);

        System.Threading.Thread.Sleep(1000);

        monitor.TryTake(out int result);
        monitorOut.Add(result);
    });

    Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}

// Max concurrency: 391
[Test]
public void Test()
{
    ConcurrentBag<int> monitor = new ConcurrentBag<int>();
    ConcurrentBag<int> monitorOut = new ConcurrentBag<int>();
    var arrayStrings = new string[1000];
    var options = new ParallelOptions {MaxDegreeOfParallelism = int.MaxValue};
    Parallel.ForEach<string>(arrayStrings, options, someString =>
    {
        monitor.Add(monitor.Count);

        System.Threading.Thread.Sleep(100000);

        monitor.TryTake(out int result);
        monitorOut.Add(result);
    });

    Console.WriteLine("Max concurrency: " + monitorOut.OrderByDescending(x => x).First());
}

설정 설정을 권장합니다 ParallelOptions.MaxDegreeOfParallelism. 반드시 사용중인 스레드 수를 늘리지는 않지만 제정신 수의 스레드 만 시작할 수 있습니다.

마지막으로 귀하의 질문에 답하기 위해 모든 스레드가 한 번에 시작되지는 않습니다. 병렬로 호환하려는 경우 평행을 사용하십시오. 예를 들어 경쟁 조건을 테스트하십시오.

// 636462943623363344
// 636462943623363344
// 636462943623363344
// 636462943623363344
// 636462943623363344
// 636462943623368346
// 636462943623368346
// 636462943623373351
// 636462943623393364
// 636462943623393364
[Test]
public void Test()
{
    ConcurrentBag<string> monitor = new ConcurrentBag<string>();
    ConcurrentBag<string> monitorOut = new ConcurrentBag<string>();
    var arrayStrings = new string[1000];
    var options = new ParallelOptions {MaxDegreeOfParallelism = int.MaxValue};
    Parallel.ForEach<string>(arrayStrings, options, someString =>
    {
        monitor.Add(DateTime.UtcNow.Ticks.ToString());
        monitor.TryTake(out string result);
        monitorOut.Add(result);
    });

    var startTimes = monitorOut.OrderBy(x => x.ToString()).ToList();
    Console.WriteLine(string.Join(Environment.NewLine, startTimes.Take(10)));
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top