need help understanding `Task`s
if my CPU has 6 cores and 12 threads, how many
Task
s can run at once?57 Replies
Any number
Tasks are not related to threads
i tried running 99 tasks at once, but they seem to be limited to 12, why is that so?
i also have this code
the time taken is always different, between 5.0s, 5.5s and 6.0s. i'm not sure why
Tasks are not exactly concurrent processes. You have a limited number of threads for processing a queue of tasks. They will process as threads become available.
You're also using
thread.Sleep()
which blocks the thread
Use await Task.Delay()
instead, so that the thread gets freed for another task to executeyea, but based on my understanding, if there are 12 threads processing the tasks, why can the code above run in less than 6 seconds?
Because you're telling a thread to not work for a set amount of time with
thread.Sleep()
as the other person said.but wouldn't that cause the time taken to be longer than 6 seconds? my concern is that it takes less than 6 seconds
I don't get why your
Process
is recursivei want them to keep taking integers from the queue until it's depleted
A loop is the normal way, which doesn't risk blowing the stack
there are 72 integers in the queue, so there are essentially 72 things to do
So you want 72 functions on the stack until the queue is empty?
i want to make 99 tasks that collectively dequeue until it's empty yes
and measure the time
but every dequeue waits 1 second
also popping from a queue recursively is not using a queue correctly.
Anyway,
Task.Run
runs ona a ThreadPool thread. The ThreadPool has a variable number of threads, and if it runs out, it will start increasing the number of threads at a rate of a couple a second (IIRC)this is not some sort of production code or best practices code, it's just what i randomly wrote to test out concurrency
how would you explain why the code above runs in less than 6 seconds?
if i run the code, it would say 5.50 s
on my 6c/12t cpu, i just want to know how this works
The default is something like 4? So you'll start off with 4-ish tasks in parallel, then after 0.5s or so another couple will start, then 0.5s after that the first 4 finish and another 4 items start processing, and at the same time another couple of threads get added
cpu thread != c# thread.
Start logging when each task start/stops, and what thread ID it's running on, that'll make it clearer
so a cpu thread can be instructed to do multiple c# threads?
No, C# threads map 1-1 to CPU threads
now i'm getting conflicting answers.
That wouldn't make sense with your previous comment about increasing number of threads.
ok i will try that
Well, OS threads, not "CPU threads". There's no such thing as a "CPU thread"
Well, unless you're getting into the realm of hyperthreading. But cpu cores/ virtual cores / etc aren't relevant here
True, but just wanted to differentiate as he was wondering why a 6c/12t cpu was not being reflected given his test code
oh wow, here are the logs
Log the starts, and timestamps as well
initially only threads 1-12, but after some time there are threads 13-16
Yeah, as I say, the thread pool will start adding threads after you exhaust all the threads it does have
with timestamps
Add milliseconds to that. You should see jumps as a loads of threads finish at the same time, and jumps as new threads are added
so if 4 threads are added, meaning there are now 16 threads, how many of these threads are actually executing in parallel?
12?
There's no reason you won't be using all of the available threads in the threadpool at the same time
but there's a limitation to how many tasks my cpu can take at an instant right
are you saying all the threads in the threadpool execute at the same time? then my question is how is this possible
A thread that's sleeping won't be running on a CPU
omg
Thread.Sleep just means "Start running again in X seconds"
okay that's the answer to my question
so if i have 16 threads, none of them is sleeping (doing some intensive task), how many would be executing at the same time?
actually i'm gonna do that experiment and see what happens
As many as your cpu allows for.
that would be my first guess, let me try it
Just mind it maybe not be 12 if you have a 6c/12t CPU... Your computer is doing other things that isn't just running your program.
thats actually handled at OS level, has to do with context switches and a lot other different complex stuff
Well. They'll all be "executing" at the same time, but what happens in reality is that the OS gives each thread a time-slice, then puts it to sleep and moves onto the next one. Your CPU hardware determines how many threads can actually be executing in parallel at the same time
i'm trying to simulate an intensive task that isn't sleeping, i'm currently using
for (int i = 0; i < int.MaxValue; i++) {}
seems like only 12 threads are spawned
at mostThe threadpool should keep spawning new ones, IIRC
the starting size of the thread pool is at least hardware dependent and might be OS dependent as well, for windows i have seen that its usually logical processors, as in ur hardware threads
you're right, i ran the code for longer and now threads 13, 14 start showing up
i see, that makes sense from the experiments that i've done
there are some different factors that can bring the thread pool to more than that.
one is for example tasks that are created
TaskCreationOptions.LongRunning
, for this often its own thread is created, that may or may not die laterTaskCreationOptions.LongRunning
doesn't touch the threadpool at all
It just does new Thread()
i thought i have read somewhere that that thread can later be added to the thread pool as well, might be misremembering
Nope, at least last time I read that code, it's just a little standalone thread
https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs,45
indeed, sorry for the misinformation.
Looks like ThreadPool.MinThreads defaults to the processor count btw: https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.cs,120
but in the end its finishing that early because its spawning new threads and thats why u finish in such a short time, like canton7 already said
logical processor count at that, so each hardware thread counts towards this
also, 1 second already counts being a long running task, iirc
if u just want to parallelize cpu bound work, u would use other means than popping a lot of tasks:
https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/data-parallelism-task-parallel-library
Data Parallelism (Task Parallel Library) - .NET
Read how the Task Parallel Library (TPL) supports data parallelism to do the same operation concurrently on a source collection or array's elements in .NET.
sure thing, i'll keep that in mind
but the reason why i'm playing with concurrency is because i'm presenting about it so i thought of using c# as an example