Barrier thread synchronisation in pairs - multithreading

I want to implement a function that blocks incoming threads until 2 threads of the same colour meet. Each thread is modelled by a unique id and colour. The function should return the id of the other thread it is matched to. I tried to use the idea for rendezvous and barrier to solve the question, which worked when there are only 2 threads at any one time, but when there are more than 2 threads, the id returned is incorrect. I am trying to solve for 1 colour first as the other 2 colors would have similar logic, but I am not sure what I need to change?
int pack_thread(int colour, int id) {
if (colour == 1) {
sem_wait(&d); map[0][count[0]] = id; count[0]++;
if (count[0] == 1) {
sem_post(&d);
sem_post(&a1); sem_wait(&a2); sem_post(&barr);
return map[0][1];
} else if (count[0] == 2) {
sem_post(&d);
sem_wait(&a1); sem_post(&a2);
return map[0][0];
} else {
sem_post(&d);
sem_wait(&barr);
map[0][1] = id;
count[0] = 0;
sem_post(&a2);sem_wait(&a1);
return map[0][0];
}
} else {
return 0;
}

Related

How to recreate swapchain after vkAcquireNextImageKHR is VK_SUBOPTIMAL_KHR?

This vulkan tutorial discusses swapchain recreation:
You could also decide to [recreate the swapchain] that if the swap chain is suboptimal, but I've chosen to proceed anyway in that case because we've already acquired an image.
My question is: how would one recreate the swapchain and not proceed in this case of VK_SUBOPTIMAL_KHR?
To see what I mean, let's look at the tutorial's render function:
void drawFrame() {
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
uint32_t imageIndex;
VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
recreateSwapChain();
return;
/* else if (result == VK_SUBOPTIMAL_KHR) { createSwapchain(); ??? } */
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
throw std::runtime_error("failed to acquire swap chain image!");
}
if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
}
imagesInFlight[imageIndex] = inFlightFences[currentFrame];
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]};
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffers[imageIndex];
VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]};
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
vkResetFences(device, 1, &inFlightFences[currentFrame]);
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) {
throw std::runtime_error("failed to submit draw command buffer!");
}
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
VkSwapchainKHR swapChains[] = {swapChain};
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;
result = vkQueuePresentKHR(presentQueue, &presentInfo);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) {
framebufferResized = false;
recreateSwapChain();
} else if (result != VK_SUCCESS) {
throw std::runtime_error("failed to present swap chain image!");
}
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
The trouble is as follows:
vkAcquireImageKHR succeeds, signaling the semaphore and returning a valid, suboptimal image
Recreate the swapchain
We can't present the image from 1 with the swapchain from 2 due to VUID-VkPresentInfoKHR-pImageIndices-01430. We need to call vkAcquireImageKHR again to get a new image.
When we call vkAcquireImageKHR again, the semaphore is in the signaled state which is not allowed (VUID-vkAcquireNextImageKHR-semaphore-01286), we need to 'unsignal' it.
Is the best solution here to destroy and recreate the semaphore?
Ad 3: you can use the old images (and swapchain) if you properly use the oldSwapchain parameter when creating the new swapchain. Which is what I assume the tutorial suggests.
Anyway. What I do is that I paranoidly sanitize that toxic semaphore like this:
// cleanup dangerous semaphore with signal pending from vkAcquireNextImageKHR (tie it to a specific queue)
// https://github.com/KhronosGroup/Vulkan-Docs/issues/1059
void cleanupUnsafeSemaphore( VkQueue queue, VkSemaphore semaphore ){
const VkPipelineStageFlags psw = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
VkSubmitInfo submit_info = {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &semaphore;
submit_info.pWaitDstStageMask;
vkQueueSubmit( queue, 1, &submit_info, VK_NULL_HANDLE );
}
After that the semaphore can be properly catched with a fence or vkQueueWaitIdle, and then destroyed or reused.
I just destroy them, because the new semaphore count might differ, and I don't really consider swapchain recreation a hotspot (and also I just use vkDeviceWaitIdle in such case).

cs50 tideman lock_paiors function issue

hi guys im having problome with my lockpairs functinog on pset3 tideman would love some feedback ty
bool checkcycle(int from, int to)
{
if(from == to)
{
return true;
}
int i;
for (i = 0; i < candidate_count; i++)
{
if(locked[from][i])
{
checkcycle(i,to);
}
}
return false;
}
void lock_pairs(void)
{
for (int i = 0; i < candidate_count; i++)
{
if(!checkcycle(pairs[i].winner , pairs[i].loser))
{
locked[pairs[i].winner][pairs[i].loser] = true;
}
return;
}
}
:( lock_pairs locks all pairs when no cycles
lock_pairs did not lock all pairs
:( lock_pairs skips final pair if it creates cycle
lock_pairs did not correctly lock all non-cyclical pairs
:( lock_pairs skips middle pair if it creates a cycle
lock_pairs did not correctly lock all non-cyclical pairs
Your checkcycle function just need a little adjustment. I would change from to winner and to to loser. I think it would be easier to understand. Given a pair, you will call checkcycle(winner, loser). After checking if winner == loser, you should iterate over all pairs checking if loser is the winner, and calling checkcycle(winner, loser), passing the same original winner, and the loser of the loser

Why is the following a memory leak? [duplicate]

I've got code that looks like this:
for (std::list<item*>::iterator i=items.begin();i!=items.end();i++)
{
bool isActive = (*i)->update();
//if (!isActive)
// items.remove(*i);
//else
other_code_involving(*i);
}
items.remove_if(CheckItemNotActive);
I'd like remove inactive items immediately after update them, inorder to avoid walking the list again. But if I add the commented-out lines, I get an error when I get to i++: "List iterator not incrementable". I tried some alternates which didn't increment in the for statement, but I couldn't get anything to work.
What's the best way to remove items as you are walking a std::list?
You have to increment the iterator first (with i++) and then remove the previous element (e.g., by using the returned value from i++). You can change the code to a while loop like so:
std::list<item*>::iterator i = items.begin();
while (i != items.end())
{
bool isActive = (*i)->update();
if (!isActive)
{
items.erase(i++); // alternatively, i = items.erase(i);
}
else
{
other_code_involving(*i);
++i;
}
}
You want to do:
i= items.erase(i);
That will correctly update the iterator to point to the location after the iterator you removed.
You need to do the combination of Kristo's answer and MSN's:
// Note: Using the pre-increment operator is preferred for iterators because
// there can be a performance gain.
//
// Note: As long as you are iterating from beginning to end, without inserting
// along the way you can safely save end once; otherwise get it at the
// top of each loop.
std::list< item * >::iterator iter = items.begin();
std::list< item * >::iterator end = items.end();
while (iter != end)
{
item * pItem = *iter;
if (pItem->update() == true)
{
other_code_involving(pItem);
++iter;
}
else
{
// BTW, who is deleting pItem, a.k.a. (*iter)?
iter = items.erase(iter);
}
}
Of course, the most efficient and SuperCool® STL savy thing would be something like this:
// This implementation of update executes other_code_involving(Item *) if
// this instance needs updating.
//
// This method returns true if this still needs future updates.
//
bool Item::update(void)
{
if (m_needsUpdates == true)
{
m_needsUpdates = other_code_involving(this);
}
return (m_needsUpdates);
}
// This call does everything the previous loop did!!! (Including the fact
// that it isn't deleting the items that are erased!)
items.remove_if(std::not1(std::mem_fun(&Item::update)));
I have sumup it, here is the three method with example:
1. using while loop
list<int> lst{4, 1, 2, 3, 5};
auto it = lst.begin();
while (it != lst.end()){
if((*it % 2) == 1){
it = lst.erase(it);// erase and go to next
} else{
++it; // go to next
}
}
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
2. using remove_if member funtion in list:
list<int> lst{4, 1, 2, 3, 5};
lst.remove_if([](int a){return a % 2 == 1;});
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
3. using std::remove_if funtion combining with erase member function:
list<int> lst{4, 1, 2, 3, 5};
lst.erase(std::remove_if(lst.begin(), lst.end(), [](int a){
return a % 2 == 1;
}), lst.end());
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
4. using for loop , should note update the iterator:
list<int> lst{4, 1, 2, 3, 5};
for(auto it = lst.begin(); it != lst.end();++it){
if ((*it % 2) == 1){
it = lst.erase(it); erase and go to next(erase will return the next iterator)
--it; // as it will be add again in for, so we go back one step
}
}
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
Use std::remove_if algorithm.
Edit:
Work with collections should be like:
prepare collection.
process collection.
Life will be easier if you won't mix this steps.
std::remove_if. or list::remove_if ( if you know that you work with list and not with the TCollection )
std::for_each
The alternative for loop version to Kristo's answer.
You lose some efficiency, you go backwards and then forward again when deleting but in exchange for the extra iterator increment you can have the iterator declared in the loop scope and the code looking a bit cleaner. What to choose depends on priorities of the moment.
The answer was totally out of time, I know...
typedef std::list<item*>::iterator item_iterator;
for(item_iterator i = items.begin(); i != items.end(); ++i)
{
bool isActive = (*i)->update();
if (!isActive)
{
items.erase(i--);
}
else
{
other_code_involving(*i);
}
}
Here's an example using a for loop that iterates the list and increments or revalidates the iterator in the event of an item being removed during traversal of the list.
for(auto i = items.begin(); i != items.end();)
{
if(bool isActive = (*i)->update())
{
other_code_involving(*i);
++i;
}
else
{
i = items.erase(i);
}
}
items.remove_if(CheckItemNotActive);
Removal invalidates only the iterators that point to the elements that are removed.
So in this case after removing *i , i is invalidated and you cannot do increment on it.
What you can do is first save the iterator of element that is to be removed , then increment the iterator and then remove the saved one.
If you think of the std::list like a queue, then you can dequeue and enqueue all the items that you want to keep, but only dequeue (and not enqueue) the item you want to remove. Here's an example where I want to remove 5 from a list containing the numbers 1-10...
std::list<int> myList;
int size = myList.size(); // The size needs to be saved to iterate through the whole thing
for (int i = 0; i < size; ++i)
{
int val = myList.back()
myList.pop_back() // dequeue
if (val != 5)
{
myList.push_front(val) // enqueue if not 5
}
}
myList will now only have numbers 1-4 and 6-10.
Iterating backwards avoids the effect of erasing an element on the remaining elements to be traversed:
typedef list<item*> list_t;
for ( list_t::iterator it = items.end() ; it != items.begin() ; ) {
--it;
bool remove = <determine whether to remove>
if ( remove ) {
items.erase( it );
}
}
PS: see this, e.g., regarding backward iteration.
PS2: I did not thoroughly tested if it handles well erasing elements at the ends.
You can write
std::list<item*>::iterator i = items.begin();
while (i != items.end())
{
bool isActive = (*i)->update();
if (!isActive) {
i = items.erase(i);
} else {
other_code_involving(*i);
i++;
}
}
You can write equivalent code with std::list::remove_if, which is less verbose and more explicit
items.remove_if([] (item*i) {
bool isActive = (*i)->update();
if (!isActive)
return true;
other_code_involving(*i);
return false;
});
The std::vector::erase std::remove_if idiom should be used when items is a vector instead of a list to keep compexity at O(n) - or in case you write generic code and items might be a container with no effective way to erase single items (like a vector)
items.erase(std::remove_if(begin(items), end(items), [] (item*i) {
bool isActive = (*i)->update();
if (!isActive)
return true;
other_code_involving(*i);
return false;
}));
do while loop, it's flexable and fast and easy to read and write.
auto textRegion = m_pdfTextRegions.begin();
while(textRegion != m_pdfTextRegions.end())
{
if ((*textRegion)->glyphs.empty())
{
m_pdfTextRegions.erase(textRegion);
textRegion = m_pdfTextRegions.begin();
}
else
textRegion++;
}
I'd like to share my method. This method also allows the insertion of the element to the back of the list during iteration
#include <iostream>
#include <list>
int main(int argc, char **argv) {
std::list<int> d;
for (int i = 0; i < 12; ++i) {
d.push_back(i);
}
auto it = d.begin();
int nelem = d.size(); // number of current elements
for (int ielem = 0; ielem < nelem; ++ielem) {
auto &i = *it;
if (i % 2 == 0) {
it = d.erase(it);
} else {
if (i % 3 == 0) {
d.push_back(3*i);
}
++it;
}
}
for (auto i : d) {
std::cout << i << ", ";
}
std::cout << std::endl;
// result should be: 1, 3, 5, 7, 9, 11, 9, 27,
return 0;
}
I think you have a bug there, I code this way:
for (std::list<CAudioChannel *>::iterator itAudioChannel = audioChannels.begin();
itAudioChannel != audioChannels.end(); )
{
CAudioChannel *audioChannel = *itAudioChannel;
std::list<CAudioChannel *>::iterator itCurrentAudioChannel = itAudioChannel;
itAudioChannel++;
if (audioChannel->destroyMe)
{
audioChannels.erase(itCurrentAudioChannel);
delete audioChannel;
continue;
}
audioChannel->Mix(outBuffer, numSamples);
}

Multithreaded merge sort Stack Overflow error

I'm trying to make a multithreaded merge sort and I've encountered a stack overflow error and I'm not sure what is causing it.
public static void concurrentMergeSort(int[] arr, int threadCount) {
if(threadCount <= 1){
regularMergeSort(arr);
return;
}
int middle = arr.length/2;
int[] left = Arrays.copyOfRange(arr, 0, middle); //Says error here
int[] right = Arrays.copyOfRange(arr, middle, arr.length);
concurrentMergeSort(left);//Says error here
concurrentMergeSort(right);
Thread leftSort = new Thread(new Sorting(left, threadCount));
Thread rightSort = new Thread(new Sorting(right, threadCount));
try{
leftSort.join();
rightSort.join();
}
catch (Exception ex){
ex.printStackTrace();
}
merge(arr, left, right);
}
public static void regularMergeSort(int[] arr){
if(arr.length == 1){
return;
}
int middle = arr.length/2;
int[] left = Arrays.copyOfRange(arr, 0, middle);
int[] right = Arrays.copyOfRange(arr, middle, arr.length);
regularMergeSort(left);
regularMergeSort(right);
merge(arr, left, right);
}
}
I was thinking that maybe it was the thread count never decreasing, but when I modify the thread count I still get the same result. Also it was working until I added a regular merge sort and concurrent merge sort to separate it. I only added the regular merge sort as well because I was barely getting a speed increase from just having the concurrent merge sort method and the main purpose of this modification of merge sort is to increase the time it takes to sort with multithreading.
Your return condition from regularMergeSort is:
if(arr.length == 1)
When middle = 0, you will end up creating an empty array; and this terminating condition won't be hit, and there will be infinite loop. Change this condition to:
if(arr.length <= 1)
And assuming your merge function handles empty arrays, you should be good.

Verify if two lists share values in C#

I'd like to know if two lists share values before applying an intersection. Something like bool DoIntersect(listA, listB) would be fabulous!
This is the code I came up with:
// Person is a class with Id and Name properties
List<Person> people1;
List<Person> people2;
// Populate people1 and people2...
// My current solution (pseudocode obviously)...
if (DoIntersect(people1, people2))
{
people1 = people1.Intersect(people2)
}
else
{
/* No shared people */
throw exception;
}
// Continue with the process...
It depends on exactly what you want:
// are there any common values between a and b?
public static bool SharesAnyValueWith<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
return a.Intersect(b).Any();
}
For lists that don't overlap, this will iterate through a and b each once. For lists that overlap, this will iterate all the way through a, then through b until the first overlapping element is found.
// does a contain all of b? (ignores duplicates)
public static bool ContainsAllFrom<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
return !b.Except(a).Any();
}
This will iterate through a once, then will iterate through b, stopping on the first element in b not in a.
// does a contain all of b? (considers duplicates)
public static bool ContainsAllFrom<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
// get the count of each distinct element in a
var counts = a.GroupBy(t => t).ToDictionary(g => g.Key, g => g.Count());
foreach (var t in b) {
int count;
// if t isn't in a or has too few occurrences return false. Otherwise, reduce
// the count by 1
if (!counts.TryGetValue(t, out count) || count == 0) { return false; }
counts[t] = count - 1;
}
return true;
}
Similarly, this will iterate through a once, then will iterate through b, stopping on the first element in b not in a.
I believe without altering the fact that you're using a List you can't get better performance.
However, if you would have 2 sorted lists to begin with (requires overhead when creating them), then you could iterate through them with complexity of O(n) in order to find out if you have shared values.
Edit:
Although original OP doesn't have 2 sorted lists, in case someone will need it, here is the implementation for checking Intersection at O(n):
public Boolean DoIntersect(SortedList<int,String> listA,SortedList<int,String> listB )
{
if (listA == null || listA.Count == 0 || listB == null || listB.Count == 0)
{
return false;
}
var keysA = listA.Keys;
var keysB = listB.Keys;
int i = 0, j = 0;
while (i < listA.Count && j < listB.Count)
{
if (keysA[i] < keysB[j])
{
i++;
}else if (keysA[i] > keysB[j])
{
j++;
}
else
{
return true;
}
}
The above approach can be used also with IEnumerable lists, given that they are sorted, with slight variation - using GetEnumerator and iterating with it.

Resources