Programing

다른 CPU 코어에서 스레드를 어떻게 생성합니까?

lottogame 2020. 12. 12. 09:57
반응형

다른 CPU 코어에서 스레드를 어떻게 생성합니까?


WAV 파일 목록을 MP3로 인코딩하는 것과 같이 계산 비용이 많이 드는 작업을 수행하는 C # 프로그램이 있다고 가정 해 보겠습니다. 보통은 파일을 한 번에 하나씩 인코딩하지만 프로그램이 내가 보유한 CPU 코어 수를 파악하고 각 코어에서 인코딩 스레드를 회전시키기를 원한다고 가정 해 보겠습니다. 그래서 제가 쿼드 코어 CPU에서 프로그램을 실행할 때, 프로그램은 그것이 쿼드 코어 CPU라는 것을 알아 내고, 작업 할 4 개의 코어가 있음을 알아 낸 다음 인코딩을위한 4 개의 스레드를 생성합니다. CPU. 어떻게해야합니까?

코어가 여러 물리적 CPU에 분산되어 있다면 이것이 다를까요? 에서처럼 두 개의 쿼드 코어 CPU가있는 컴퓨터가있는 경우 특별한 고려 사항이 있습니까? 아니면 Windows에서 두 다이의 8 개 코어가 동일한 것으로 간주됩니까?


그렇게 귀찮게하지 마십시오.

대신 스레드 풀을 사용하십시오 . 스레드 풀은 새 스레드를 쿼리 할 수있는 프레임 워크의 메커니즘 (실제로는 클래스)입니다.

새 스레드를 요청하면 새 스레드를 제공하거나 스레드가 해제 될 때까지 작업을 대기열에 추가합니다. 그런 식으로 프레임 워크는 현재 CPU 수에 의존하지 않고 더 많은 스레드를 생성할지 여부를 결정합니다.

편집 : 또한 이미 언급했듯이 OS는 여러 CPU간에 스레드를 배포하는 역할을합니다.


스레드 풀을 사용하는 것만 큼 간단하지는 않습니다.

기본적으로 스레드 풀은 각 CPU에 여러 스레드를 할당합니다. 작업에 참여하는 모든 스레드에는 비용 (작업 전환 오버 헤드, CPU의 매우 제한된 L1, L2 및 L3 캐시 사용 등)이 있으므로 사용할 최적의 스레드 수는 <=입니다. 사용 가능한 CPU의 수 (각 스레드가 확장 성이 뛰어난 웹 서비스와 같은 다른 시스템에서 서비스를 요청하지 않는 경우) 일부 경우, 특히 CPU 활동보다 더 많은 하드 디스크 읽기 및 쓰기가 필요한 경우에는 실제로 여러 스레드보다 1 개의 스레드를 사용하는 것이 더 나을 수 있습니다.

대부분의 응용 프로그램과 WAV 및 MP3 인코딩의 경우 작업자 스레드 수를 사용 가능한 CPU 수로 제한해야합니다. 다음은 CPU 수를 찾는 C # 코드입니다.

int processors = 1;
string processorsStr = System.Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS");
if (processorsStr != null)
    processors = int.Parse(processorsStr);

안타깝게도 CPU 수에 제한을 두는 것만 큼 간단하지 않습니다. 또한 하드 디스크 컨트롤러 및 디스크의 성능을 고려해야합니다.

최적의 스레드 수를 실제로 찾을 수있는 유일한 방법은 시도 오류입니다. 이것은 특히 하드 디스크, 웹 서비스 등을 사용하는 경우에 해당됩니다. 하드 디스크의 경우 쿼드 프로세서 CPU에서 4 개의 프로세서를 모두 사용하지 않는 것이 좋습니다. 반면에 일부 웹 서비스에서는 CPU 당 10 개 또는 100 개의 요청을 만드는 것이 더 나을 수 있습니다.


관리 스레드의 경우이를 수행하는 복잡성이 네이티브 스레드보다 훨씬 더 큽니다. 이는 CLR 스레드가 기본 OS 스레드에 직접 연결되어 있지 않기 때문입니다. 즉, CLR은 적절하다고 판단되는대로 관리 스레드를 네이티브 스레드에서 네이티브 스레드로 전환 할 수 있습니다. Thread.BeginThreadAffinity 함수 는 기본 OS 스레드와 잠금 단계에서 관리 스레드를 배치하기 위해 제공됩니다. 이 시점에서 네이티브 API를 사용하여 기본 네이티브 스레드 프로세서 선호도를 제공하는 실험을 할 수 있습니다. 모두가 여기에서 제안했듯이 이것은 좋은 생각이 아닙니다. 실제로 스레드가 단일 프로세서 또는 코어로 제한되는 경우 스레드가 더 적은 처리 시간을받을 수 있음을 제안하는 문서있습니다.

System.Diagnostics.Process 클래스를 탐색 할 수도 있습니다 . 거기에서 프로세스의 스레드를 ProcessThread 개체 의 컬렉션으로 열거하는 함수를 찾을 수 있습니다 . 이 클래스에는 ProcessorAffinity를 설정하거나 선호하는 프로세서를 설정하는 메서드 가 있습니다.

면책 조항 : CPU 사용률이 낮다고 생각하고이 항목을 많이 조사한 비슷한 문제가 발생했습니다. 그러나 내가 읽은 모든 내용에 따르면 여기에 게시 된 의견에서도 알 수 있듯이 좋은 생각이 아닌 것으로 나타났습니다. 그러나 실험하는 것은 여전히 ​​흥미롭고 학습 경험입니다.


여기에있는 대부분의 답변에 동의하지만 새로운 고려 사항 인 Speedstep 기술을 추가 할 가치가 있다고 생각합니다.

멀티 코어 시스템에서 CPU 집약적 인 단일 스레드 작업을 실행할 때 Windows 서버 2012에서 6 개의 실제 코어 (HT가있는 12 개)를 사용하는 Xeon E5-2430에서 작업은 다음을 사용하여 12 개 코어 모두에 분산되었습니다. 각 코어의 약 8.33 %이며 속도 증가를 유발하지 않습니다. CPU는 1.2GHz로 유지되었습니다.

스레드 선호도를 특정 코어로 설정하면 해당 코어의 ~ 100 %를 사용하여 CPU가 2.5GHz에서 최대가되어 성능이 두 배 이상 증가했습니다.

이것은 변수를 증가시키는 루프 만 사용하는 프로그램입니다. -a와 함께 호출하면 선호도가 코어 1로 설정됩니다. 선호도 부분은 이 게시물 을 기반으로 했습니다 .

using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;

namespace Esquenta
{
    class Program
    {
        private static int numThreads = 1;
        static bool affinity = false;
        static void Main(string[] args)
        {
            if (args.Contains("-a"))
            {
                affinity = true;
            }
            if (args.Length < 1 || !int.TryParse(args[0], out numThreads))
            {
                numThreads = 1;
            }
            Console.WriteLine("numThreads:" + numThreads);
            for (int j = 0; j < numThreads; j++)
            {
                var param = new ParameterizedThreadStart(EsquentaP);
                var thread = new Thread(param);
                thread.Start(j);
            }

        }

        static void EsquentaP(object numero_obj)
        {
            int i = 0;
            DateTime ultimo = DateTime.Now;
            if(affinity)
            {
                Thread.BeginThreadAffinity();
                CurrentThread.ProcessorAffinity = new IntPtr(1);
            }
            try
            {
                while (true)
                {
                    i++;
                    if (i == int.MaxValue)
                    {
                        i = 0;
                        var lps = int.MaxValue / (DateTime.Now - ultimo).TotalSeconds / 1000000;
                        Console.WriteLine("Thread " + numero_obj + " " + lps.ToString("0.000") + " M loops/s");
                        ultimo = DateTime.Now;
                    }
                }
            }
            finally
            {
                Thread.EndThreadAffinity();
            }
        }

        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();

        [DllImport("kernel32.dll")]
        public static extern int GetCurrentProcessorNumber();
        private static ProcessThread CurrentThread
        {
            get
            {
                int id = GetCurrentThreadId();
                return Process.GetCurrentProcess().Threads.Cast<ProcessThread>().Single(x => x.Id == id);
            }
        }
    }
}

결과 :

results

CPU-Z가보고하는 것과 유사한 작업 관리자에 의해 표시되는 프로세서 속도 :

enter image description here


프로그램 내부에 루틴을 작성하여이를 수행 할 수 있습니다.

However you should not try to do it, since the Operating System is the best candidate to manage these stuff. I mean user mode program should not do try to do it.

However, sometimes, it can be done (for really advanced user) to achieve the load balancing and even to find out true multi thread multi core problem (data racing/cache coherence...) as different threads would be truly executing on different processor.

Having said that, if you still want to achieve we can do it in the following way. I am providing you the pseudo code for(Windows OS), however they could easily be done on Linux as well.

#define MAX_CORE 256
processor_mask[MAX_CORE] = {0};
core_number = 0;

Call GetLogicalProcessorInformation();
// From Here we calculate the core_number and also we populate the process_mask[] array
// which would be used later on to set to run different threads on different CORES.


for(j = 0; j < THREAD_POOL_SIZE; j++)
Call SetThreadAffinityMask(hThread[j],processor_mask[j]);
//hThread is the array of handles of thread.
//Now if your number of threads are higher than the actual number of cores,
// you can use reset the counters(j) once you reach to the "core_number".

After the above routine is called, the threads would always be executing in the following manner:

Thread1-> Core1
Thread2-> Core2
Thread3-> Core3
Thread4-> Core4
Thread5-> Core5
Thread6-> Core6
Thread7-> Core7
Thread8-> Core8

Thread9-> Core1
Thread10-> Core2
...............

For more information, please refer to manual/MSDN to know more about these concepts.


You shouldn't have to worry about doing this yourself. I have multithreaded .NET apps running on dual-quad machines, and no matter how the threads are started, whether via the ThreadPool or manually, I see a nice even distribution of work across all cores.


Where each thread goes is generally handled by the OS itself...so generate 4 threads on a 4 core system and the OS will decide which cores to run each on, which will usually be 1 thread on each core.


It is the operating system's job to split threads across different cores, and it will do so when automatically when your threads are using a lot of CPU time. Don't worry about that. As for finding out how many cores your user has, try Environment.ProcessorCount in C#.


you cannot do this, as only operating system has the privileges to do it. If you will decide it.....then it will be difficult to code applications. Because then you also need to take care for inter-processor communication. critical sections. for each application you have to create you own semaphores or mutex......to which operating system gives a common solution by doing it itself.......


One of the reasons you should not (as has been said) try to allocated this sort of stuff yourself, is that you just don't have enough information to do it properly, particularly into the future with NUMA, etc.

If you have a thread read-to-run, and there's a core idle, the kernel will run your thread, don't worry.

참고URL : https://stackoverflow.com/questions/32343/how-do-i-spawn-threads-on-different-cpu-cores

반응형