Comments (12)
I think I can support the upgrade lock cleanly as well. This is a pretty general concept. You can get a shared lock, a unique lock, and if necessary you can upgrade a shared lock to a unique lock.
from parallel-hashmap.
Hi Vinnie,
The current version uses a more flexible locking mechanism which should support boost::shared_mutex and boost::upgrade_mutex, although I haven't tested with these yet. The only location internally where we actually upgrade the mutex, though, is in erase
(so we don't unique_lock if we attempt to erase a value that is not present).
In order for this to work, the boost mutex headers have to be included before phmap.h.
from parallel-hashmap.
Hi Vinnie, I validated the use of the boost::upgrade_mutex in phmap (which is the same class as shared_mutex), so closing the ticket. Feel free to ask if you have further questions.
from parallel-hashmap.
This is a very good point. I'll look into improving the interface (template parameter) to allow for this use case.
Indeed you can work around this, but it would be nicer if the parallel hashmap supported this natively.
from parallel-hashmap.
it would be nicer if the parallel hashmap supported this natively.
I'm not sure that I agree. Human creativity is effectively infinite, and it is unreasonable to expect that the parallel hashmap should handle every imaginable use-case simply by adjusting one template parameter. Instead, I would consider simply making sure that the functionality exposed by the hashmap (adding members if necessary) is sufficiently flexible that authors who desire custom behavior are able to achieve it through efficient composition of the hashmap container.
For example, I would consider the normal hashmap interface to be "sufficient flexible" if it is possible to build a parallel hashmap from it with no loss of performance, using only the public interfaces (is it?)
from parallel-hashmap.
I was thinking that instead of providing a mutex as a template parameter, I could allow for a class that has two lock/unlock methods, so you'd be able to use for example:
class StdLockable {
public:
void lock() { m_.lock(); }
void unlock() { m_.unlock(); }
void lock_shared() { m_.lock(); }
void unlock_shared() { m_.unlock(); }
private:
std::mutex m_;
};
class SharedLockable{
public:
void lock() { m_.lock(); }
void unlock() { m_.unlock(); }
void lock_shared() { m_.lock_shared(); }
void unlock_shared() { m_.unlock_shared(); }
private:
boost::shared_mutex m_;
};
Internally the phmap would use lock_shared for the red APIs and lock for the mutable ones.
from parallel-hashmap.
For example, I would consider the normal hashmap interface to be "sufficient flexible" if it is possible to build a parallel hashmap from it with no loss of performance, using only the public interfaces (is it?)
No it isn't. For example there is no way to avoid recomputing the hash in the internal submaps using the std interface.
from parallel-hashmap.
there is no way to avoid recomputing the hash in the internal submaps using the std interface.
Then I would explore this direction. Is there a clean way to provide an interface that avoids the recomputation of the hash?
I suggest this because, mutexes are notoriously difficult to compose. You can have a parallel hashmap with a built-in mutex that works great by itself, but then when you add surrounding code that has its own mutex and locking, it no longer works ideally. For example, you might want to atomically insert two elements at once. This is not possible if the mutex is an implementation detail of the parallel map. To support these use-cases, it is sufficient to allow users to build up arbitrarily complex parallel maps using the regular map as a building block - as you have pointed out, there needs to be some visibility and control over how and when hashes are calculated for this to work efficiently.
from parallel-hashmap.
Well, for complicated use cases as you suggest, it is better to keep the locking separate. I don't really see the use case where the additional interface you suggest would be useful.
However, I still think that internal locking can be convenient for simple use cases, and that I need to support shared_locks.
from parallel-hashmap.
I still think that internal locking can be convenient for simple use cases, and that I need to support shared_locks.
Okay. What about upgrade locks then? On insertion, acquire the shared lock to determine if the element already exists, and then if not, upgrade the shared lock to an exclusive lock to modify the map.
from parallel-hashmap.
So the sequence is something like this?
m.lock_upgrade();
find();
if (present)
{
m.unlock_upgrade();
return;
}
m.lock();
insert_item();
m.unlock();
m.unlock_upgrade(); // not sure about that last one
from parallel-hashmap.
The UpgradeLockable concept is a Boost extension, you can read about it here:
https://www.boost.org/doc/libs/1_69_0/doc/html/thread/synchronization.html#thread.synchronization.mutex_concepts.upgrade_lockable
I bring up the upgrade lock approach not because I am suggesting that you should implement it, but to show how there are uncountably many different approaches, and tying the parallel hashmap to one solution will necessarily disadvantage others.
from parallel-hashmap.
Related Issues (20)
- LLDB pretty-printer is buggy HOT 2
- Avoid Memory Reallocations in flat_hash_map clear for Trivial Classes HOT 3
- Suggestion: lazy_emplace_l without last argument HOT 12
- Unused variable warning HOT 2
- question about performance of `at(...)` HOT 4
- Iteration Order Differs on Arm64 Architecture HOT 4
- Very minor optimization: _mm_abs_epi8 instead of _mm_sign_epi8 HOT 1
- Slow in a specific case HOT 20
- asan build on linux failed with memory error HOT 3
- In template: constexpr variable 'kFirst' must be initialized by a constant expression HOT 6
- phmap_dump saving a lot more than needed HOT 4
- Thread safe way to check existence of items HOT 8
- is it possible to miss the necessary .cmake in the conda packaging? HOT 1
- nvc++: integer conversion resulted in a change of sign HOT 9
- Need a tag about `reserve` bug HOT 3
- Need help speeding up large hash map HOT 6
- merging maps HOT 8
- Release memory after shrinking HOT 6
- Memory not reclaimed after calling map.clear() HOT 4
- Ability to reset the inner sub map HOT 64
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from parallel-hashmap.