Is it allowed to record CommandBuffers on multiple threads which were allocated from the same pool? - vulkan

Suppose we have a CommandPool with two CommandBuffers allocated from it (CommandBuffer1, CommandBuffer2).
The CommandPool lives on Thread 0, CommandBuffer1 and CommandBuffer2 also live on Thread 0.
Is it possible to transfer CommandBuffer1 and CommandBuffer1 to a different thread to record commands? With the restriction that only one thread is allowed the record a CommandBuffer at the same time?
The spec states
Command pools are application-synchronized, meaning that a command pool must not be used concurrently in multiple threads. That includes use via recording commands on any command buffers allocated from the pool, as well as operations that allocate, free, and reset command buffers or the pool itself.
I am not quite sure if I would be allowed to record CommandBuffer1 on Thread 1 and CommandBuffer2 on Thread 2 at the same time.
Or do I have to record all CommandBuffers on the same thread that they were allocated from?

There is a list of "Implicit Externally Synchronized Parameters" in chapter 2.5. Threading Behavior that has a list mostly consisting of:
The VkCommandPool that commandBuffer was allocated from, in vkCmd*
So no it's not possible to record 2 command buffers from the same pool on different threads.
Though it is strange that vkBeginCommandBuffer and vkEndCommandBuffer isn't in that list.

Who's forcing you to have only one pool though?
Have one pool per thread. Problem solved.
Yes, you do not have to use them on the same thread. You just must make sure that:
[...]command pool must not be used concurrently in multiple threads.
If you (for some obscure reason) want to use the pool on different thread, you must stop using it on the original thread (via using synchronization primitives) before you start using it on the second thread.

Related

Why is there more DB connection pool than main thread in Webflux?

I use Webflux R2DBC.
I know, the default value creates 1 thread per CPU core.
However, I know that the default value of R2DBC's connection pool is 10.
I can't understood that....
DB connections operate asynchronously. Then, DB connection don't need many thread pool.
Because the DB connection only sends and receives, connection can do other work(other sending or receiving) while waiting for it.
Rather, since the main thread(1 per CPU core) performs various calculations, the number of main threads should be large.
What am I missing?
I think you kind of have it backwards.
since the main thread(1 per CPU core) performs various calculations, the number of main threads should be large.
A (logical) CPU can perform only one task at a time and since threads in a reactive application should never just wait, since all calls are non-blocking, it doesn't make sense to have more threads than CPU's.
DB connections operate asynchronously. Then, DB connection don't need many thread pool.
Correct, you don't need a thread pool for your database connectivity. But a connection pool isn't a thread pool. I holds connections. Database connections are still expensive to create, so you want to reuse them and database transactions are bound to the database connection, so you need multiple connections in order to process different requests in separate transactions.
Of course how big a connection pool should be is a completely different and rather complex question.

Should one minimize the number of command pools an application creates?

Say that there is a queue family which supports presentation to a surface, and graphics. Is it better (due to technical reasons) to create a single command pool which handles presentation and graphics, or is it better to create two command pools: one the application will use only for graphics (even though it could use it for presentation) and another the application will use only for presentation (even though it could use it for graphics)?
Essentially, should one minimize the number of command pools associated with a particular queue family? Or is it okay to create as many command pools as one desires? More generally (regardless of which queue family the command pools are associated with), should an application minimize how many command pools it creates?
EDIT: I wrote "queues" instead of "command pools" in the initial version of this post. This has been fixed.
The main purpose of a command pool is to be a (mostly) single-threaded allocator for the storage used by a set of command buffers which are filled by that thread. You create pools to serve that purpose.
So if you have three threads that need to generate commands for a particular queue, then you create 3 pools, one for each such thread, and use them to generate the CBs you are interested in.
And depending on your CB resetting strategy, you may want to multi-buffer pools. That is, while a thread is generating commands into CBs from pool A, the GPU is reading from CBs from pool B. That way, when the GPU is done, you can just reset the pool rather than resetting the individual CBs.
The overall point is that you create command pools to serve your application's allocation and CB-building strategy. The association of a pool with a queue family is there solely to help the implementation generate commands for those CBs more efficiently. You should not assume that a pool is consuming some kind of limited resource from the queue.

In Hazelcast, is it possible to use clustered locks that do _not_ care about the local thread that performs the lock/unlock operations?

Hazelcast locks (such as http://www.hazelcast.com/docs/1.9.4/manual/multi_html/ch02s07.html) as I understand it behave the same way as the Java concurrency primitives but across the cluster. The makes it possible to use to synchronize between thread in the local process as well as over the cluster.
However, is there any way I can opt out of this behaviour? In my current project, I need a way of coordinating unique ownership of a resource across the cluster but want to aquire and release this ownership from multiple points in my application - can I do this in some way that does not involve dedicating a thread to managing this lock in my process?
The Semaphore is your friend because it doesn't have a concept of ownership. It uses permits that can be acquired; thread x can acquire permit 1, but thread y can release permit 1. If you initialize the semaphore with a single permit, you will get your mutual exclusion.
ISemaphore s = hazelcastInstance.getSemaphore("foo");
s.init(1);
s.acquire();
And in another thread you can release this permit by:
ISemaphore s = hazelcastInstance.getSemaphore("foo");
s.release();

Will detached NSThreads always complete prior to application exit?

When using NSThread's detachNewThreadSelector:toTarget:withObject:, I'm finding that the thread will fully complete its execution before the application is terminated normally if the user were to attempt to quit the application while the background process was executing.
In this case, this is the behavior I desire, but I couldn't find anything in Apple's docs that suggests that this will always be the case. The only relevant information I was able to find was the following, from Apple's Threading Programming Guide:
Important: At application exit time, detached threads can be terminated immediately but joinable threads cannot. Each joinable thread must be joined before the process is allowed to exit. Joinable threads may therefore be preferable in cases where the thread is doing critical work that should not be interrupted, such as saving data to disk.
So from this, I know that detached threads can be terminated at the time of application exit, but will they ever be terminated automatically? Or, am I always safe to assume the thread will complete its execution before the application quits?
You cannot assume that any thread -- including the main thread -- will ever complete execution normally, regardless of the documentation.
This is because the user can quit an application at any time, the system may lose power/panic, or the app may crash.
As for detached threads, it would not be unheard of for the system frameworks to automatically terminate the app forcibly after some timeout once the main event loop has given up the ghost.

How to cause locks to be freed in one thread which were set by another

I have a simple thread pool written in pthreads implemented using a pool of locks so I know which threads are available. Each thread also has a condition variable it waits on so I can signal it to do work.
When work comes in, I pick a thread by looking finding an available thread from the lock pool. I then set a data structure associated with the thread that contains the work it needs to do and signal on the condition variable that the thread should start working.
The problem is when the thread completes work. I need to unlock the thread in the lock pool so it's available for more work. However, the controlling thread is the one which set the lock, so the thread can't free this lock itself. (And the controlling thread doesn't know when work is done.)
Any suggestions?
I could rearchitect my thread pool to use a queue where all threads are signaled when work is added so one thread can grab it. However, in the future, thread affinity will likely be a problem for incoming work and the lock pool makes implementation of this easier.
It seems to me that the piece of data that you're trying to synchronize access to is the free/busy status of each thread.
So, have a table (array) that records the free/busy status of each thread, and use a mutex to protect access to that table. Any thread (controller or worker) that wants to examine/change the thread status needs to seize the mutex, but the lock needs to be held only while the status is being examined/changed, not for the entire duration of the thread's work.
To assign work to a thread, you would do:
pthread_mutex_lock(&thread_status_table_lock);
-- search table for available thread
-- assign work to that thread
-- set thread status to "busy"
pthread_mutex_unlock(&thread_status_table_lock);
-- signal the thread
And when the thread finishes its work, it would change its status back to "free":
pthread_mutex_lock(&thread_status_table_lock);
-- set thread status to "free"
pthread_mutex_unlock(&thread_status_table_lock);