Improve efficiency of stored function calling
Previously, every called function iterated through all entities for calling the function on matching entities. Now, callForMatchingFunctions iterates through all entities once, stores matching entities for each function, then calls the functions on the matching entities.
This commit is contained in:
parent
248cf2676a
commit
6b0e950c84
1 changed files with 134 additions and 55 deletions
|
@ -763,7 +763,11 @@ namespace EC
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::size_t, std::function<void(std::size_t)> >
|
std::unordered_map<std::size_t, std::tuple<
|
||||||
|
BitsetType,
|
||||||
|
std::function<void(
|
||||||
|
std::size_t,
|
||||||
|
std::vector<std::size_t>)> > >
|
||||||
forMatchingFunctions;
|
forMatchingFunctions;
|
||||||
std::size_t functionIndex = 0;
|
std::size_t functionIndex = 0;
|
||||||
|
|
||||||
|
@ -827,58 +831,43 @@ namespace EC
|
||||||
|
|
||||||
forMatchingFunctions.emplace(std::make_pair(
|
forMatchingFunctions.emplace(std::make_pair(
|
||||||
functionIndex,
|
functionIndex,
|
||||||
[function, signatureBitset, helper, this]
|
std::make_tuple(
|
||||||
(std::size_t threadCount)
|
signatureBitset,
|
||||||
|
[function, helper, this]
|
||||||
|
(std::size_t threadCount,
|
||||||
|
std::vector<std::size_t> matching)
|
||||||
{
|
{
|
||||||
if(threadCount <= 1)
|
if(threadCount <= 1)
|
||||||
{
|
{
|
||||||
for(std::size_t i = 0; i < this->currentSize; ++i)
|
for(auto eid : matching)
|
||||||
{
|
{
|
||||||
if(!std::get<bool>(this->entities[i]))
|
helper.callInstancePtr(eid, *this, &function);
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if((signatureBitset
|
|
||||||
& std::get<BitsetType>(this->entities[i]))
|
|
||||||
== signatureBitset)
|
|
||||||
{
|
|
||||||
helper.callInstancePtr(i, *this, &function);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<std::thread> threads(threadCount);
|
std::vector<std::thread> threads(threadCount);
|
||||||
std::size_t s = this->currentSize / threadCount;
|
std::size_t s = matching.size() / threadCount;
|
||||||
for(std::size_t i = 0; i < threadCount; ++ i)
|
for(std::size_t i = 0; i < threadCount; ++ i)
|
||||||
{
|
{
|
||||||
std::size_t begin = s * i;
|
std::size_t begin = s * i;
|
||||||
std::size_t end;
|
std::size_t end;
|
||||||
if(i == threadCount - 1)
|
if(i == threadCount - 1)
|
||||||
{
|
{
|
||||||
end = this->currentSize;
|
end = matching.size();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
end = s * (i + 1);
|
end = s * (i + 1);
|
||||||
}
|
}
|
||||||
threads[i] = std::thread(
|
threads[i] = std::thread(
|
||||||
[this, &function, &signatureBitset, &helper]
|
[this, &function, &helper]
|
||||||
(std::size_t begin,
|
(std::size_t begin,
|
||||||
std::size_t end) {
|
std::size_t end) {
|
||||||
for(std::size_t i = begin; i < end; ++i)
|
for(std::size_t i = begin; i < end; ++i)
|
||||||
{
|
|
||||||
if(!std::get<bool>(this->entities[i]))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if((signatureBitset
|
|
||||||
& std::get<BitsetType>(this->entities[i]))
|
|
||||||
== signatureBitset)
|
|
||||||
{
|
{
|
||||||
helper.callInstancePtr(i, *this, &function);
|
helper.callInstancePtr(i, *this, &function);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
begin, end);
|
begin, end);
|
||||||
}
|
}
|
||||||
|
@ -887,11 +876,86 @@ namespace EC
|
||||||
threads[i].join();
|
threads[i].join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
})));
|
||||||
|
|
||||||
return functionIndex++;
|
return functionIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::vector<std::size_t> > getMatchingEntities(
|
||||||
|
std::vector<BitsetType*> bitsets, std::size_t threadCount = 1)
|
||||||
|
{
|
||||||
|
std::vector<std::vector<std::size_t> > matchingV(bitsets.size());
|
||||||
|
|
||||||
|
if(threadCount <= 1)
|
||||||
|
{
|
||||||
|
for(std::size_t i = 0; i < currentSize; ++i)
|
||||||
|
{
|
||||||
|
if(!isAlive(i))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for(std::size_t j = 0; j < bitsets.size(); ++j)
|
||||||
|
{
|
||||||
|
if(((*bitsets[j]) & std::get<BitsetType>(entities[i]))
|
||||||
|
== (*bitsets[j]))
|
||||||
|
{
|
||||||
|
matchingV[j].push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::vector<std::thread> threads(threadCount);
|
||||||
|
std::size_t s = currentSize / threadCount;
|
||||||
|
std::mutex mutex;
|
||||||
|
for(std::size_t i = 0; i < threadCount; ++i)
|
||||||
|
{
|
||||||
|
std::size_t begin = s * i;
|
||||||
|
std::size_t end;
|
||||||
|
if(i == threadCount - 1)
|
||||||
|
{
|
||||||
|
end = currentSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
end = s * (i + 1);
|
||||||
|
}
|
||||||
|
threads[i] = std::thread(
|
||||||
|
[this, &matchingV, &bitsets, &mutex]
|
||||||
|
(std::size_t begin, std::size_t end)
|
||||||
|
{
|
||||||
|
for(std::size_t j = begin; j < end; ++j)
|
||||||
|
{
|
||||||
|
if(!isAlive(j))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for(std::size_t k = 0; k < bitsets.size(); ++k)
|
||||||
|
{
|
||||||
|
if(((*bitsets[k]) &
|
||||||
|
std::get<BitsetType>(entities[j]))
|
||||||
|
== (*bitsets[k]))
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(mutex);
|
||||||
|
matchingV[k].push_back(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, begin, end);
|
||||||
|
}
|
||||||
|
for(std::size_t i = 0; i < threadCount; ++i)
|
||||||
|
{
|
||||||
|
threads[i].join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchingV;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Call all stored functions.
|
\brief Call all stored functions.
|
||||||
|
|
||||||
|
@ -922,11 +986,23 @@ namespace EC
|
||||||
*/
|
*/
|
||||||
void callForMatchingFunctions(std::size_t threadCount = 1)
|
void callForMatchingFunctions(std::size_t threadCount = 1)
|
||||||
{
|
{
|
||||||
for(auto functionIter = forMatchingFunctions.begin();
|
std::vector<BitsetType*> bitsets;
|
||||||
functionIter != forMatchingFunctions.end();
|
for(auto iter = forMatchingFunctions.begin();
|
||||||
++functionIter)
|
iter != forMatchingFunctions.end();
|
||||||
|
++iter)
|
||||||
{
|
{
|
||||||
functionIter->second(threadCount);
|
bitsets.push_back(&std::get<BitsetType>(iter->second));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::vector<std::size_t> > matching =
|
||||||
|
getMatchingEntities(bitsets, threadCount);
|
||||||
|
|
||||||
|
std::size_t i = 0;
|
||||||
|
for(auto iter = forMatchingFunctions.begin();
|
||||||
|
iter != forMatchingFunctions.end();
|
||||||
|
++iter)
|
||||||
|
{
|
||||||
|
std::get<1>(iter->second)(threadCount, matching[i++]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -966,7 +1042,10 @@ namespace EC
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
iter->second(threadCount);
|
std::vector<std::vector<std::size_t> > matching =
|
||||||
|
getMatchingEntities(std::vector<BitsetType*>{
|
||||||
|
&std::get<BitsetType>(iter->second)}, threadCount);
|
||||||
|
std::get<1>(iter->second)(threadCount, matching[0]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue