Si te refieres a hilos soportados por hardware (Hyperthreading de Intel, por ejemplo), puedes buscar la arquitectura del chip específico que estás utilizando. O, si conoces el número de núcleos físicos, las herramientas del sistema operativo suelen revelar el número de núcleos virtuales del sistema. Por ejemplo, el administrador de tareas de Windows en mi portátil aquí mostrará ocho CPUs, pero en realidad sólo tengo cuatro núcleos, cada uno de los cuales tiene dos hilos de hardware.
Esa no es ciertamente la única manera de hacerlo. Y hay procesadores con hasta ocho hilos de hardware (respuesta de Dave Haynie's a ¿Es posible que un núcleo de CPU tenga tres o cuatro hilos y cómo afectará esto al rendimiento?) Pero no es muy probable que los encuentre, a menos que trabaje en un centro de datos.
En cuanto a los hilos de software, cada CPU [virtual] tiene uno. El multithreading por software es la multiplexación por división de tiempo de un recurso de la CPU. Un hilo se ejecuta durante un tiempo, entonces hay algún evento - una espera en un recurso de E/S, un temporizador a nivel de sistema - que señala un intercambio de tareas. El sistema operativo busca las prioridades en la cola de tareas pendientes y programa los siguientes N hilos, uno por núcleo virtual. Pero hasta que el hilo se ejecuta realmente, existe como un trozo de memoria en algún lugar, no está "en" ningún núcleo.
Es posible, pero raro, que a un hilo se le asigne específicamente una "afinidad" por un núcleo específico en un sistema. Un ejemplo sería una máquina virtual - hay muy buenas razones para asignar una VM a un solo núcleo. Algunas arquitecturas de ordenadores multiproceso no son totalmente simétricas. Por ejemplo, los primeros sistemas de multiprocesamiento de Macintosh sólo tenían una CPU que podía manejar las interrupciones. Así que todo el procesamiento de las interrupciones tenía que ocurrir en esa única CPU, sin importar cuántos núcleos tuviera en realidad.
En términos de software, hay otras razones. Cuando se dice "hilo" en el software, se suele hablar de la unidad más pequeña de ejecución de código. Un hilo prácticamente sólo se ocupa del contexto de la propia CPU. Frente a "proceso", que incluye la gestión de recursos y el seguimiento de las asignaciones de E/S, los contextos de la MMU, etc. Puedo escribir una aplicación multiproceso en sistemas basados en UNIX utilizando la función fork(), que es realmente fácil de usar (divide un proceso en dos procesos), pero utiliza muchos recursos. Puedo utilizar hilos en la mayoría de los sistemas operativos, que son mucho más bajos en cuanto a sobrecarga. Sin embargo, cada hilo dentro de un programa se ejecuta en el mismo contexto de proceso. Así que un programador inteligente puede darse cuenta de eso cuando llegue la siguiente ronda de programación, e intercambiar nuevos hilos en el mismo contexto de proceso, lo que significa la misma CPU. No es un requisito, sólo una optimización para reducir la sobrecarga de la programación.