In particular, can I create pipelines, allocate device memory and create images and buffers from the same VkDevice concurrently?
Where in the specs this is specified?
In the specification we can read:
Vulkan is intended to provide scalable performance when used on multiple host threads. All commands support being called concurrently from multiple threads, but certain parameters, or components of parameters are defined to be externally synchronized. This means that the caller must guarantee that no more than one thread is using such a parameter at a given time.
Then there is a list of parameters of different Vulkan functions in which they must be externally synchronized (meaning they cannot be accessed at the same time from multiple threads). In case of a VkDevice objects, we can find that only vkDestroyDevice(). So all other usages of a VkDevice objects can happen on multiple threads.
And there are practically no vkCreate...() functions in that list (only 3 swapchain related functions). Which means you can create objects from multiple threads at the same time.
Statements in the Vulkan specification of the form "host access to X must be externally synchronized" mean that you cannot cause accesses to X while also calling the function that has this requirement. If a function's specification doesn't say that about a particular parameter, then that parameter can be accessed from multiple threads. So long as all functions that could concurrently access it don't have this specification, of course.
Note that the Valid Usage section of various functions can have additional concurrency requirements.
Related
So a VkSampler is created with a VkSamplerCreateInfo that just has a bunch of configuration settings, that as far as I can see would just define a pure function of some input image.
They are described as:
VkSampler objects represent the state of an image sampler which is used by the implementation to
read image data and apply filtering and other transformations for the shader.
One use (possibly only use) of VkSampler is to write them to descriptors (such as VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) for use in descriptor sets that are bound to pipelines/shaders.
My question is: can you write the same VkSampler to multiple different descriptors? from the same or multiple different descriptor pools? even if one of the current descriptors is in use in some currently executing render pass?
Can you use the same VkSampler concurrently from multiple different render passes / subpasses / pipelines?
Put another way, are VkSamplers stateless? or do they represent some stateful memory on the device and so you shouldn't use the same one concurrently?
VkSampler objects definitely have data associated with them, so it would be wrong to call them "stateless". What they are is immutable. Like VkRenderPass, VkPipeline, and similar objects, once they are created, their contents cannot be changed.
Synchronization between accesses is (generally) needed only for cases when one of the accesses is a modification operation. Since VkSamplers are immutable, there are no modification operations. So synchronization is not needed for cases where you're accessing a VkSampler from different threads, commands, or whathaveyou.
The only exception is the obvious one: vkDestroySampler, which requires that submitted commands that use the sampler have completed before calling the function.
Reading the docs for Spark I see
The data broadcasted this way is cached in serialized form and deserialized before running each task. This means that explicitly creating broadcast variables is only useful when tasks across multiple stages need the same data or when caching the data in deserialized form is important.
I understand why broadcasts variables are useful when re-using them in multiple tasks. You don't want to re-send them with all closures.
However the second part, in bold, says when caching data in deserialized form is important. When and why would that be important? If you're only going to use data in 1 task it will still get serialized/deserialized once, no?
I think you ignored following part:
and deserialized before running each task.
A single stage typically consist of multiple tasks (it is not common to have only a single partition, is it?) and multiple tasks belonging to the same stage can be processed by the same executor. Since deserialization can be quite expensive you may prefer to perform it only once.
I am working with contiki and trying to understand the terminology used in it.
I am observing certain words such as yield, stackless here and there on internet. Some examples
PROCESS_EVENT_CONTINUE : This event is sent by the kernel to a process that is waiting in a PROCESS_YIELD() statement.
PROCESS_YIELD(); // Wait for any event, equivalent to PROCESS_WAIT_EVENT().
PROCESS_WAIT_UNTIL(); // Wait for a given condition; may not yield the process.
Does yielding a process means, executing a process in contiki. Also what does it mean that contiki is stackless.
Contiki uses so-called protothreads (a Contiki-specific term) in order to support multiple application-level processes in this OS. Protothread is just a fancy name for a programming abstraction known as coroutine in computer science.
"Yield" in this context is short for "yield execution" (i.e. give up execution). It means "let other protothreads to execute until an event appears that is addressed to the current protothread". Such events can be generated both by other protothreads and by interrupt handler functions. The "wait" macros are similar, but allow to yield and wait for specific events or conditions.
Contiki protothreads are stackless in the sense that they all share the same global stack of execution, as opposed to "real" threads which typically get their own stack space. As a consequence, the values local variables are not preserved in Contiki protothreads across yields. For example, doing this is undefined behavior:
int i = 1;
PROCESS_YIELD();
printf("i=%d\n", i); // <- prints garbage
The traditional Contiki way how deal with this limitation is to declare all protothread-local variables as static:
static int i = 1;
PROCESS_YIELD();
printf("i=%d\n", i);
Other options is to use global variables, of course, but having a lot of global variables is bad programming style. The benefit of static variables declared inside protothread functions is that they are hidden from other functions (including other protothreads), even though at the low level they are allocated in the global static memory region.
In the general case, to "Yield" in any OS means to synchronously invoke the scheduler (i.e. on demand rather then through interrupt) in order to give the opportunity of control to some other thread. In an RTOS such a feature would only affect threads of the same priority, and may be used in addition or instead of pre-emptive round-robin scheduling is required. Most RTOS do not have an explicit yield function, or in some cases (such as VxWorks) the same effect can be achieved using a zero length delay.
In a cooperative scheduler such as that in Contiki, such a function is necessary to allow other threads to run in an otherwise non-blocking thread. A thread always has control until it calls a bocking or yielding function.
The cooperative nature of Contiki's scheduler mean that it cannot be classified as an RTOS. It may be possible to achieve real-time behaviour suitable to a specific application, but only through careful and appropriate application design, rather the through intrinsic scheduler behaviour.
Consider two problems:
We have a wrapper that detects if the wrapped object started a transaction, keeps the transaction number and makes it available to users of wrapper through a method. Can it be called a facade, assuming it simplifies interface of course?
There is a communication layer which provides high-level interface for low-level operations required to execute functions on attached device (these involves pushing bytes through socket and parsing the answers). Some of the answers contains a special "prompt number" which is required for some other queries. Communication layer detects answers which contains a prompt number and stores that number in a special holder which is available to caller. Could that be called a facade?
Overall those questions are related to a more general question:
Which design patterns allows to store or manage mutable or immutable state and/ or inspect the objects that are passed to wrapped objects or returned from them.
Take a look at the Observer Pattern http://en.wikipedia.org/wiki/Observer_pattern
The State pattern could be of use as well: http://en.wikipedia.org/wiki/State_pattern
and perhaps also Memento http://en.wikipedia.org/wiki/Memento_pattern
depending on what you want to accomplish.
For the Observer look at boost signals and slots or at qt signals and slots for some neat implementation.
I am in vb.net and have a function that will be accessed by multiple threads. Everything inside the function uses local variables. However, each thread will pass in its own dataset by reference.
From what I have read the local variables should be no problem, but I think the dataset coming in is a concern.
How should I control access / execution of this function to make sure that it is thread safe? Thanks.
Assuming that by 'dataset' you mean a System.Data.DataSet, if your function is only reading from the dataset, then you don't need synchronization in any case since "This type is safe for multithreaded read operations" (from http://msdn.microsoft.com/en-us/library/system.data.dataset.aspx).
If you're modifying the dataset, then as long as each dataset is a different instance, there should be no problem.
If you're modifying the data and if different threads might pass in a reference to the same dataset, you'll need to synchronize access to the dataset using a Monitor (SyncLock or lock in C#) or some other synchronization technique.