Microsoft MVP성태의 닷넷 이야기
닷넷: 2263. C# - Thread가 Task보다 더 빠르다는 어떤 예제(?) [링크 복사], [링크+제목 복사],
조회: 12261
글쓴 사람
정성태 (seongtaejeong at gmail.com)
홈페이지
첨부 파일
 

C# - Thread가 Task보다 더 빠르다는 어떤 예제(?)

아래의 글에 대해,

6 ways to use parallelism with Tasks and Threads in C# .NET
; https://medium.com/@saulodacruz1999/6-ways-to-use-parallelism-with-tasks-and-threads-in-c-net-20c8bbd62102

이런 의견을 다루고 있는데요,

Thread가 Task보다 더 빠르다는 어떤 예제
; https://forum.dotnetdev.kr/t/thread-task/10745

그러니까, 원본 글을 쓴 사람이 11초가 걸린다는 아래의 코드를 보면,

var count = 0;
var anyObject = new object();
UseTasks();

void UseTasks()
{
    var tasks = new List<Task>();

    for (int i = 0; i < 100; i++)
    {
        var task = new Task(() =>
        {
            AnyMethod();
            lock (anyObject) count++;
        });

        task.Start();
        tasks.Add(task);
    }

    Task.WaitAll(tasks.ToArray());
}

void AnyMethod() => Thread.Sleep(1000);

// Time spent: 11 seconds

(Thread로 직접 구현하면 2초가 걸린다고 하는데, 이게 좀 이상하군요, 이론상 1초 정도에 끝납니다. 아마도 EXE 수준에서의 실행 시간을 측정한 것이 아닌가... 합니다.) Task로 구현해 11초가 걸린다고 합니다. 그런데, 사실 이 문제는 Thread나 Task의 비교에서 올 것이 아닙니다. 왜냐하면 둘 다 결국 Thread로 스케줄링이 될 뿐, 저렇게 차이가 나며 실행될 여지가 없기 때문입니다.

그렇다면 왜 저런 결과가 나오는 것일까요?

저건 Task 자체의 문제는 아니고, (Task가 기반을 둔) ThreadPool의 스레드 운영 정책에서 기인합니다. 이에 대해서는 전에도 한 번 설명한 적이 있습니다.

ThreadPool.QueueUserWorkItem의 실행 지연
; https://www.sysnet.pe.kr/2/0/1455

따라서, 100개의 스레드를 쓸 것이라는 가정을 한다면 애당초 그만큼 미리 스레드를 (별다른 조건 없이 빠르게) 준비하도록 다음과 같이 설정해 주면 됩니다.

ThreadPool.SetMinThreads(100, 100);

Stopwatch st = new Stopwatch();
st.Start();
// ...[이하 Task 사용 코드]....
st.Stop();
Console.WriteLine(st.ElapsedMilliseconds); // 출력 결과: 1022

1022ms니까, Task를 사용했어도 1초 내에 거의 마무리가 된 것입니다.




사실, "6 ways to use parallelism with Tasks and Threads in C# .NET" 글의 Task 예제를 각자의 컴퓨터에서 돌려보면 11초가 아닌, 다른 시간이 나올 수 있습니다.

다시 말하지만, 이것은 ThreadPool의 정책으로 인해 미리 만들어 둔 스레드의 수가 문제인 건데요, 가령 제 컴퓨터에서는,

ThreadPool.GetMinThreads(out int workerThreads, out _);
Console.WriteLine($"{workerThreads}"); // 출력 결과: 24

미리 만들어 둔 스레드가 24개이므로 100개의 작업에 나뉘므로 대략 걸리는 시간을 이런 식으로 추측할 수 있습니다.

int expected = (int) Math.Ceiling(100.0f / workerThreads);
Console.WriteLine(expected); // 출력 결과: 5

실제로 (SetMinThreads 호출 없이) 제 컴퓨터에서 Task 예제를 돌리면 (11초가 아닌) 5040ms 정도의 시간이 걸리는 것을 확인할 수 있습니다. (물론, 저런 예측 시간 계산은 스레드풀의 스레드가 증가할 시간 내이기 때문에 거의 정확하게 들어맞은 것입니다. 그렇지 않은 경우라면 중간에 스레드를 늘리기 때문에 예측치가 빗나갈 수 있습니다.)

참고로, 왜 제 컴퓨터에서는 24개의 MinThread가 나왔을까요?

그것은, 24 HT/Core를 갖고 있기 때문입니다. ^^ 그리고 이런 것은 이미 문서에 어느 정도 공개돼 있는 내용입니다.

ThreadPool.GetMinThreads(Int32, Int32) Method
; https://learn.microsoft.com/en-us/dotnet/api/system.threading.threadpool.getminthreads

By default, the minimum number of threads is set to the number of processors on a system. When the minimum is reached, the thread pool can create additional threads in that category or wait until some tasks complete




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 5/22/2024]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 121  122  123  124  125  126  127  128  129  130  131  132  [133]  134  135  ...
NoWriterDateCnt.TitleFile(s)
1822정성태12/3/201428215개발 환경 구성: 252. Xamarin 라이선스 관리 [8]
1821정성태12/1/201435906VS.NET IDE: 96. Visual Studio에서 /* ~ */ 주석을 위한 단축키(매크로)
1820정성태11/23/201423309.NET Framework: 485. Mono Profiler에서 IL 코드 변경이 가능할까? - 두 번째 이야기파일 다운로드1
1819정성태11/22/201423230오류 유형: 264. MSBuild 에러 - warning MSB3052: The parameter to the compiler is invalid,
1818정성태11/22/201426773개발 환경 구성: 251. NUMA 노드 수에 따른 IIS Worker Process(w3wp.exe) 설정 [1]
1817정성태11/22/201429909VS.NET IDE: 95. Macros for Visual Studio 2013 [1]
1816정성태11/20/201424426.NET Framework: 484. Mono Profiler에서 IL 코드 변경이 가능할까?
1815정성태11/18/201422474.NET Framework: 483. 코드로 살펴 보는 ETW의 활성화 시점 [2]
1814정성태11/18/201423970오류 유형: 263. Unable to find the requested .Net Framework Data Provider. It may not be installed.
1813정성태11/18/201425396오류 유형: 262. Build Events에 robocopy 작업이 있는 경우 "VCEnd exited with code 3" 오류 발생
1812정성태11/17/201423754.NET Framework: 482. ETW 자동 생성 코드의 VerificationException 예외 발생
1811정성태11/16/201425236.NET Framework: 481. Mono 내부의 문자열 처리 방식은 UTF-8
1810정성태11/15/201462432.NET Framework: 480. C# - 배치 파일 실행하고 출력 결과를 얻는 방법 [4]
1809정성태11/11/201426952.NET Framework: 479. Mono Profiler를 Unity의 Plugin으로 사용하는 방법
1808정성태11/11/201426912.NET Framework: 478. C# - 폴더 경로 문자열에서 "..", "." 표기를 고려한 최종 문자열을 얻는 방법 [2]
1807정성태11/10/201433947개발 환경 구성: 250. 서버용 Socket에서 사용하는 포트가 충돌한다면?파일 다운로드1
1806정성태11/10/201429762.NET Framework: 477. SeCreateGlobalPrivilege 특권과 WCF NamedPipe
1805정성태11/5/201426042.NET Framework: 476. Visual Studio에서 Mono용 Profiler 개발 [3]파일 다운로드1
1804정성태11/5/201432307.NET Framework: 475. ETW(Event Tracing for Windows)를 C#에서 사용하는 방법 [9]파일 다운로드1
1803정성태11/4/201422889오류 유형: 261. Windows Server Backup 오류 - Error in backup of E:\$Extend\$RmMetadata\$TxfLog
1802정성태11/4/201426189오류 유형: 260. 이벤트 로그 - Windows Error Reporting / AEAPPINVW8
1801정성태11/4/201431937오류 유형: 259. 이벤트 로그 - Windows Error Reporting / IPX Assertion / KorIME.exe [1]
1800정성태11/4/201422289오류 유형: 258. 이벤트 로그 - Starting a SMART disk polling operation in Automatic mode.
1799정성태11/4/201426548오류 유형: 257. 이벤트 로그 - The WMI Performance Adapter service entered the stopped state.
1798정성태11/4/201435136오류 유형: 256. 이벤트 로그 - The WinHTTP Web Proxy Auto-Discovery Service service entered the stopped state. [1]
1797정성태11/4/201421143오류 유형: 255. 이벤트 로그 - The Adobe Flash Player Update Service service entered the stopped state.
... 121  122  123  124  125  126  127  128  129  130  131  132  [133]  134  135  ...