Supongo que lo de "directamente paralelizable" se refiere a que la función ejecuta ciertas instrucciones sobre un número n de elementos y puedes ejecutar un número n de hilos que trabajen sobre estos elementos. Ejemplo:
Se tiene una función que realiza la suma de los elementos de n arreglos. La forma tradicional de hacerlo sería:
public struct StArreglos
{
public int[] Elementos;
}
StArreglos[] VarArreglos;
public void SumaArreglos()
{
int C;
int D;
for(C = 0; C < VarArreglos.Lenght; C++)
{
for(D = 0; D < VarArreglos[C].Elementos.Lenght; D++)
{
// Suma de los elementos.
}
}
}
public void main()
{
VarArreglos
= new StArreglos
(3); SumaArreglos();
}
Esta función podríamos decir que es directamente paralelizable porque basta con reescribir la función sumar arreglos eliminando el primer bucle y pasando un índice a la función indicando sobre cual arreglo ejecutaremos la suma de sus elementos. Después, en la función main invocamos un hilo a dicha función por cada arreglo:
[code=csharp]public struct StArreglos
{
public int[] Elementos;
}
StArreglos[] VarArreglos;
public void SumaArreglos(int Indice)
{
int C;
for(D = 0; D < VarArreglos[Indice].Elementos.Lenght; D++)
{
// Suma de los elementos.
}
}
}
public void main()
{
int A;
VarArreglos
= new StArreglos
(3); for(A = 0; A < VarArreglos.Lenght; A++)
{
// Lanzo un hilo a la función 'SumaArreglos' por cada arreglo.
}
}
[/code]
Lo de desenrrollar en bucle te lo dejo aquí:
https://es.wikipedia.org/wiki/Desenroscado_de_buclesBusca la parte que dice "desenroscado de bucles estático".