작은 인스턴스에서 실행되는 WebRole이 있습니다. 이 WebRole에는 많은 양의 파일을 BLOB 저장소에 업로드하는 메서드가 있습니다. Azure 인스턴스 사양에 따르면 작은 인스턴스는 코어 1 개만입니다. 그래서 그 얼룩을 업로드 할 때 Parallel.Foreach는 정기적 인 Foreach에 비해 어떤 이점도 있습니까?작은 푸른 하늘에 Parallel.Foreach 사용
답변
blob 저장소 API 및/또는 Stream
API의 aysnc 버전 사용에 중점을두면 훨씬 편리해질 수 있으므로 CPU 경계가 아닌 I/O 경계가됩니다. BeginXXX API가있는 곳이라면 어디서나 Task.Factory.FromAsync
으로 감싸서 사용하고 거기에서 연속을 사용해야합니다. 특정 경우에는 CloudBlob.BeginUploadFromStream
을 사용해야합니다. 처음에 스트림을 얻는 방법도 마찬가지로 중요하므로 비동기 API도 찾아야합니다.
그 후에 작은 인스턴스를 사용하지 못하게하는 유일한 방법은 매체가 200Mbps 인 경우 100Mbps로 제한된다는 것입니다. 그런 다음 다시 탄성 계수를 활용하고 더 많은 처리가 필요할 때 역할 수를 늘리고 일이 진정 될 때 다시 규모를 조정할 수 있습니다.
FromAsync
을 사용하여 BeginUploadFromStream
으로 전화하는 방법의 예입니다. 자, 동시 처리 조정에 이르기까지 비동기 작업을 시작할 때부터 Parallel :: ForEach를 사용하여 최대 동시성을 제한 할 수는 없습니다. 즉, 동시 스레드를 제한하기 위해 Semaphore
이있는 원래 스레드에 정기적 인 foreach를 가짐을 의미합니다. 이 MaxDegreeOfParallelism
의 동등 제공 할 것입니다 : 당신은 또한 비동기 소스 스트림을 받고해야 어떻게 표시되지하고이 샘플 지금
// Setup a semaphore to constrain the max # of concurrent "thing"s we will process
int maxConcurrency = ... read from config ...
Semaphore maxConcurrentThingsToProcess = new Semaphore(maxConcurrency, maxConcurrency);
// Current thread will enumerate and dispatch I/O work async, this will be the only CPU resource we're holding during the async I/O
foreach(Thing thing in myThings)
{
// Make sure we haven't reached max concurrency yet
maxConcurrentThingsToProcess.WaitOne();
try
{
Stream mySourceStream = ... get the source stream from somewhere ...;
CloudBlob myCloudBlob = ... get the blob from somewhere ...;
// Begin uploading the stream asynchronously
Task uploadStreamTask = Task.Factory.FromAsync(
myCloudBlob.BeginUploadFromStream,
myCloudBlob.EndUploadFromStream,
mySourceStream,
null);
// Setup a continuation that will fire when the upload completes (regardless of success or failure)
uploadStreamTask.ContinueWith(uploadStreamAntecedent =>
{
try
{
// upload completed here, do any cleanup/post processing
}
finally
{
// Release the semaphore so the next thing can be processed
maxConcurrentThingsToProcess.Release();
}
});
}
catch
{
// Something went wrong starting to process this "thing", release the semaphore
maxConcurrentThingsToProcess.Release();
throw;
}
}
을하지만, 예를 들어, 다른 URL을 어딘가에서 해당 스트림을 다운로드 한 경우 , 당신은 그것을 비동기 적으로 없애고 비동기 업로드의 시작을 여기에 계속 연결하고 싶을 것입니다.
저는이 코드가 단순한 Parallel::ForEach
을 수행하는 것보다 더 많은 코드임을 알고 있습니다. 그러나 CPU 바인딩 작업을위한 동시성을 쉽게 만들기 위해 Parallel::ForEach
이 존재합니다. I/O와 관련하여 비동기 API를 사용하면 CPU 리소스를 최소화하면서 최대 I/O 처리량을 얻을 수있는 유일한 방법입니다.
코어 수가 Parallel.ForEach()
에 의해 생성 된 스레드 수와 직접적인 상관 관계가 없습니다.
약 1 년 전 David Aiken은 Small 인스턴스에서 Parallel.ForEach()
의 유무에 관계없이 일부 BLOB + 테이블 액세스에 대해 매우 비공식적 인 테스트를 수행했습니다. 결과는 here입니다. 이 경우, 은이었으며, 이는 CPU- 바운드 활동이 아니므로 측정 된 향상이었습니다. BLOB 저장소에 많은 수의 개체를 업로드하고 있기 때문에 성능이 향상 될 것으로 판단됩니다.
네, 업로드 할 때마다 네트워크에 연결되므로 스케쥴러가 그들 사이에 하나의 핵심을 공유 할 수 있습니다. (결국 단일 코어, 단일 CPU 컴퓨터가 한 번에 두 가지 이상의 작업을 처리하는 방법입니다.)
비슷한 효과를 위해 비동기 BLOB 업로드 기능을 사용할 수도 있습니다.
- 1. 푸른 하늘에 디스크가 가득 차 있으면 어떻게됩니까?
- 2. 데이터베이스가있는 푸른 하늘에 근무하는 사람의 역할
- 3. 푸른 하늘에 중소 기업을위한 호스팅 솔루션을 제공
- 4. Parallel.ForEach - ForEach 내부 목록 사용
- 5. 푸른 - 무시하는 방법 푸른
- 6. 델파이 XE2에서 푸른 하늘에 업로드하면 영원히 달라 붙을 것입니다. 어떻게 해결 될까요?
- 7. 푸른
- 8. 푸른
- 9. Matchcollection Parallel.Foreach
- 10. IIS와 Parallel.ForEach
- 11. # 4의 Parallel.ForEach
- 12. Parallel.ForEach 여기
- 13. 변경된 Parallel.ForEach 동작?
- 14. 푸른 하늘과 다른 응용 프로그램에서 클래스 사용 : 모니터링 딜레마
- 15. Parallel.Foreach + yield returns?
- 16. 작은 대문자 사용
- 17. Parallel.ForEach 끝에 스레드가 없습니다
- 18. Parallel.ForEach 및 ActiveX
- 19. Parallel.ForEach 및 ListView 컨트롤
- 20. Parallel.ForEach x of x
- 21. Parallel.ForEach finally 절
- 22. Parallel.Foreach Loop에서 순차적으로로드 나누기
- 23. Counter ++ in Parallel.ForEach
- 24. .NET 4 ... Parallel.ForEach() 질문
- 25. Linq In Parallel.ForEach
- 26. Reflection.Emit and Parallel.ForEach
- 27. Parallel.ForEach 사용시 발생하는 오류
- 28. Parallel.ForEach - 정상적인 취소
- 29. .NET 4.0의 Parallel.ForEach
- 30. Parallel.ForEach 루프 동작
Parallel.ForEach()를 사용하면 루프의 코드가 매우 간단합니다. CloudBlob.UploadFromStream()을 호출하기 만하면됩니다. 그러나 비동기 메서드를 사용할 때는 덜 명확합니다. CloudBlob.BeginUploadStream()을 Task에 랩핑하고 일반 foreach 루프 내에서 루프의 끝에서 Task.WaitAll()을 호출하여 작업 foreach 파일을 생성해야합니까?(훌륭한 코드 스 니펫을 제공 할 수 있다면) –
아니요, 이것은 같은 것이 아닙니다. Parallel :: ForEach 내부에서 동기식 호출을 수행하면 I/O가 발생하는 동안 해당 작업자 스레드가 차단되어 귀중한 CPU 리소스를 소비하게됩니다. 비동기 패턴을 사용하면 조금 더 많은 작업이 필요하지만 사실상 I/O가 관련되어있을 때 그 가치는 그 이상의 가치가 있습니다. 이것이 C# 5.0이 async 키워드를 추가하고 .NET 4.5의 BCL이이 새로운 Task 기반 비동기 패턴을 기반으로 재 설계되는 이유입니다. 심지어 Windows 8 API조차이 패턴을주의 깊게 따르고 있습니다. 간단한 예제를 추가하겠습니다. –
Parallel :: ForEach는 모든 것을 Tasks로 변환하기 때문에 @Drew에 동의합니다. 왜냐하면 Parallel :: ForEach는 Tasks로 모든 것을 변환하기 때문에 스레드 스케줄링은 루프의 각 반복마다 즉시 스레드를 할당하지 않기 때문입니다. 오히려 스레드가 각각의 CPU 시간을 필요로하므로 스레드 (예 : 코어 당 2 개)로 시작해야한다고 가정합니다. 결국 모든 작업이 I/O를 기다리고 있으며 더 많은 스레드를 할당하지만 시간이 걸릴 것입니다. –