thread scheduling in multi core architecture
The load balancing or multiprocessor scheduling problem is one of the earliest NP-hard problems for which an approximation algorithm has been developed.  The classic paper is:


  R.L. Graham: "Bounds for certain multiprocessing anomalies," Bell System Technical Journal, 45(9):1563–158, 1966.


In the load balancing problem you are given $M$ identical cores, and $N$ threads.  All the threads are assumed to be available at the beginning, and all the thread run times are given before hand.  Graham proved that list scheduling, taking the threads one-by-one and assigning each one to the machine that currently has the least load is a 2-approximation.  He further proved that Longest processing time (or LPT) scheduling, where you sort the threads in decreasing order of running length before doing list scheduling is a 4/3-approximation algorithm.  See, for example: https://www.cs.princeton.edu/~wayne/kleinberg-tardos/pdf/11ApproximationAlgorithms-2x2.pdf

Graham's original result has been extended over the years to cases where there are dependences between jobs (i.e., job $j$ needs to finish before job $k$ starts), and to where each job $i$ is not permitted to be scheduled before a given time $a_i$ (known as the arrival time), and to where the machines have different properties, and the jobs have requirements about what machine properties are required.

In the case where the job lengths and/or arrival times are not known before hand the problem becomes much harder.  This becomes an online algorithm.  The main research I am aware of in this area is for the case where the jobs do have dependences between them, but the dependences are restricted to fork-join patterns.  The work in this area started (afaik) with the paper


  Robert D. Blumofe; Charles E. Leiserson: Scheduling multithreaded computations by work stealing. J. ACM 46(5):720-748, 1999.


(Note that this is called "work stealing", but you should really view the work being stolen as a new, dependent, job, so it actually fits into the non-migratory requirement you specified.)

As to your other question: there has been some work in using type inference to infer program running times, but I don't know that anything practical ever came out of it.  The paper I'm aware of is:


  Brian Reistad; David K. Gifford: Static Dependent Costs for Estimating Program Execution Time, ACM Conf on Lisp and Functional Programming, 1994.