Pregunta

Digamos que yo tenía un programa en C# que hizo algo computacionalmente costosos, como la codificación de una lista de archivos WAV a Mp3.Normalmente me iba a codificar los archivos de uno en un tiempo, pero digamos que yo quería que el programa para averiguar la cantidad de núcleos de CPU que tenía y girar una codificación de hilo en cada núcleo.Así, cuando ejecuto el programa en un quad core CPU, el programa de las cifras es un quad core CPU, figuras hay cuatro núcleos a trabajar, entonces se genera a cuatro hilos para la codificación, cada uno de los cuales se ejecuta en su propio CPU.¿Cómo puedo hacer esto?

Y sería diferente si los núcleos se extendió a través de múltiples CPUs físicas?Como si yo tuviera una máquina con dos CPUs quad core en él, ¿hay alguna consideración especial o son las ocho núcleos a través de los dos muere considera igual en Windows?

¿Fue útil?

Solución

No se moleste en hacer que.

En lugar de utilizar el El Hilo De La Piscina.El hilo de la piscina es un mecanismo (en realidad, una clase) de que el marco puede consultar un nuevo hilo.

Cuando usted pide un nuevo hilo que le dará una nueva, o poner en cola el trabajo hasta que un hilo de liberarse.De esa manera, el marco es el encargado de decidir si se deben crear más hilos o no dependiendo del número de presentes Cpu.

Editar:Además, como ya se ha mencionado, el sistema operativo es el encargado de distribuir los hilos entre los diferentes CPUs.

Otros consejos

No es necesariamente tan simple como usar el hilo de la piscina.

De forma predeterminada, el grupo de subprocesos asigna varios subprocesos para cada CPU.Ya que cada hilo que se involucra en el trabajo que están haciendo tiene un costo (cambiar de tarea de la sobrecarga, el uso de la CPU, es muy limitado L1, L2 y tal vez de caché L3, etc...), el número óptimo de hilos a utilizar es <= el número de CPU - a menos que cada hilo está solicitando servicios de otras máquinas - tales como altamente escalable servicio web.En algunos casos, particularmente aquellos que involucran a más de disco duro, la lectura y la escritura de la actividad de la CPU, que en realidad puede ser mejor con 1 hilo de varios subprocesos.

Para la mayoría de las aplicaciones, y, sin duda, WAV y MP3 de la codificación, se debe limitar el número de subprocesos de trabajo a la CPU.Aquí es un poco de C# código para encontrar el número de CPU:

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

Por desgracia, no es tan simple como la limitación a la cantidad de CPU.También tienes que tener en cuenta el rendimiento de la controladora de disco duro(s) disco(s).

La única manera de que realmente se puede encontrar el número óptimo de threads juicio es un error.Esto es especialmente cierto cuando usted está usando los discos duros, los servicios web y tal.Con los discos duros, que podría ser mejor no usar los cuatro procesadores en usted procesador quad CPU.Por otro lado, con algunos servicios de la web, usted puede ser mejor hacer 10 o incluso 100 solicitudes por parte de la CPU.

En el caso de los subprocesos administrados, la complejidad de hacerlo es en un grado mayor que la de subprocesos nativos.Esto es debido a CLR hilos no están directamente ligados a un nativo de OS hilo.En otras palabras, el CLR puede cambiar administrado el hilo de los nativos del hilo a hilo nativo como lo considere oportuno.La función Subproceso.BeginThreadAffinity se proporciona a cabo un subproceso administrado en la cerradura-paso con un nativo de OS hilo.En ese punto, usted podría experimentar con el uso de la API nativa para darle el subyacente hilo nativo de la afinidad del procesador.Como todo el mundo sugiere aquí, esto no es una muy buena idea.De hecho, no hay documentación lo que sugiere que los hilos se pueden recibir menos tiempo de procesamiento si ellos están restringidos a un único procesador o núcleo.

También puede explorar la Sistema.Los diagnósticos.Proceso de clase.Allí usted puede encontrar una función para enumerar un proceso de' hilos como una colección de ProcessThread objetos.Esta clase tiene métodos para establecer ProcessorAffinity o incluso establecer un preferido procesador -- no estoy seguro de lo que es.

Descargo de responsabilidad:He experimentado un problema similar, donde pensé que la CPU(s) que estaban siendo utilizados e investigado mucho de este material;sin embargo, basado en todo lo que he leído, parece que no era una buena idea, como se evidencia por los comentarios publicados aquí.Sin embargo, todavía es muy interesante y una experiencia de aprendizaje para el experimento.

Aunque estoy de acuerdo con la mayoría de las respuestas aquí, creo que vale la pena para agregar una nueva cuenta:La tecnología Speedstep.

Cuando se ejecuta un uso intensivo de CPU, de un solo subproceso de trabajo en un sistema multi-núcleo, en mi caso un Xeon E5-2430 con 6 núcleos reales (12 con HT) en windows server 2012, el trabajo que tengo repartidos entre todos los 12 núcleos, utilizando alrededor de 8.33% de cada núcleo y nunca desencadenar un aumento en la velocidad.La CPU se mantuvo en 1,2 GHz.

Cuando me puse el hilo de la afinidad a un determinado núcleo, se utiliza ~100% de ese núcleo, causando la CPU a un máximo de 2.5 GHz, más que duplicando el rendimiento.

Este es el programa que he utilizado, que acaba de bucles el aumento de una variable.Cuando se llama con -a, establece la afinidad core 1.La afinidad parte se basa en este post.

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);
            }
        }
    }
}

Y los resultados:

results

La velocidad del procesador, como se muestra por el administrador de Tareas, de forma similar a lo que CPU-Z informes:

enter image description here

Usted no debería tener que preocuparse por hacer esto por sí mismo.He multiproceso .NET aplicaciones que se ejecutan en dual-quad máquinas, y no importa cómo los hilos se inician, ya sea a través del grupo de subprocesos o manualmente, veo una buena distribución uniforme de trabajo a través de todos los núcleos.

Definitivamente, usted puede hacer esto escribiendo la rutina dentro de su programa.

Sin embargo, usted no debe tratar de hacerlo, ya que el Sistema Operativo es el mejor candidato para manejar estas cosas.Me refiero a modo de usuario del programa no debe tratar de hacerlo.

Sin embargo, a veces, se puede hacer (por muy avanzada del usuario) para lograr el equilibrio de carga y incluso para averiguar la verdadera multi hilo multi núcleo del problema (datos de carreras y coherencia de la caché...) como de los diferentes subprocesos, sería realmente se ejecutan en diferentes procesadores.

Habiendo dicho eso, si usted todavía quiere lograr, podemos hacerlo de la siguiente manera.Yo estoy dando el pseudo código para(sistema operativo Windows), sin embargo, que podría ser fácilmente hecho en Linux.

#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".

Después de que el de arriba se llama rutina, los hilos siempre se ejecuta de la siguiente manera:

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

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

Para obtener más información, por favor consulte el manual/MSDN para saber más acerca de estos conceptos.

Donde cada hilo va generalmente es manejado por el sistema operativo en sí...así generar de 4 hilos en un 4 núcleo del sistema y el sistema operativo decide que los núcleos de ejecución de cada sobre, que normalmente será 1 hilo de cada núcleo.

Es el sistema operativo de trabajo para dividir los hilos a través de los diferentes núcleos, y lo hará de manera automática cuando los hilos están utilizando una gran cantidad de tiempo de CPU.No te preocupes por eso.Como para averiguar cuántos núcleos que su usuario tiene, trate de Environment.ProcessorCount en C#.

usted no puede hacer esto, como único sistema operativo tiene los privilegios para hacerlo.Si usted va a decidir.....entonces será difícil para código de aplicaciones.Porque también hay que tener cuidado para inter-procesador de comunicación.las secciones críticas.para cada aplicación, usted tiene que crear el propio semáforos o la exclusión mutua......para que el sistema operativo le da una solución común, haciendo de ella misma.........

Una de las razones por las que usted no debe (como se ha dicho) intentar asignados a este tipo de cosas a ti mismo, es que simplemente no tiene suficiente información para hacerlo correctamente, en particular en el futuro con NUMA, etc.

Si usted tiene un hilo de leer y ejecutar, y hay un núcleo de inactividad, el kernel se ejecutar el hilo, no te preocupes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top