Skip to content

Commit

Permalink
Color to grayscale and ParallelAlgorithms DataStore Integration
Browse files Browse the repository at this point in the history
  • Loading branch information
nyoungbq committed Jul 25, 2024
1 parent fe12389 commit c791078
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ void FindStatistics(const DataArray<T>& source, const Int32Array* featureIds, co
indexAlgArrays.push_back(mostPopulatedBinPtr);

#ifdef SIMPLNX_ENABLE_MULTICORE
if(IParallelAlgorithm::CheckArraysInMemory(indexAlgArrays))
if(detail::CheckArraysInMemory(indexAlgArrays))
{
const tbb::simple_partitioner simplePartitioner;
const size_t grainSize = 500;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include "simplnx/Common/Array.hpp"
#include "simplnx/Common/Range.hpp"
#include "simplnx/Core/Application.hpp"
#include "simplnx/Core/Preferences.hpp"
#include "simplnx/DataStructure/DataArray.hpp"
#include "simplnx/DataStructure/DataGroup.hpp"
Expand All @@ -12,11 +11,11 @@ using namespace nx::core;

namespace
{

template <bool BoundsCheckV>
class LuminosityImpl
{
public:
LuminosityImpl(const UInt8Array& data, UInt8Array& outputData, const FloatVec3& colorWeights, size_t numComp)
LuminosityImpl(const UInt8AbstractDataStore& data, UInt8AbstractDataStore& outputData, const FloatVec3& colorWeights, size_t numComp)
: m_ImageData(data)
, m_FlatImageData(outputData)
, m_ColorWeights(colorWeights)
Expand All @@ -36,9 +35,18 @@ class LuminosityImpl
{
for(size_t i = start; i < end; i++)
{
auto temp = static_cast<int32>(
roundf((m_ImageData.at(m_NumComp * i) * m_ColorWeights.getX()) + (m_ImageData.at(m_NumComp * i + 1) * m_ColorWeights.getY()) + (m_ImageData.at(m_NumComp * i + 2) * m_ColorWeights.getZ())));
m_FlatImageData.setValue(i, static_cast<uint8>(temp));
if constexpr(BoundsCheckV)
{
auto temp = static_cast<int32>(roundf((m_ImageData.at(m_NumComp * i) * m_ColorWeights.getX()) + (m_ImageData.at(m_NumComp * i + 1) * m_ColorWeights.getY()) +
(m_ImageData.at(m_NumComp * i + 2) * m_ColorWeights.getZ())));
m_FlatImageData.setValue(i, static_cast<uint8>(temp));
}
else
{
auto temp = static_cast<int32>(
roundf((m_ImageData[m_NumComp * i] * m_ColorWeights.getX()) + (m_ImageData[m_NumComp * i + 1] * m_ColorWeights.getY()) + (m_ImageData[m_NumComp * i + 2] * m_ColorWeights.getZ())));
m_FlatImageData.setValue(i, static_cast<uint8>(temp));
}
}
}

Expand All @@ -48,16 +56,16 @@ class LuminosityImpl
}

private:
const UInt8Array& m_ImageData;
UInt8Array& m_FlatImageData;
const UInt8AbstractDataStore& m_ImageData;
UInt8AbstractDataStore& m_FlatImageData;
const FloatVec3& m_ColorWeights;
size_t m_NumComp;
};

class LightnessImpl
{
public:
LightnessImpl(const UInt8Array& data, UInt8Array& outputData, size_t numComp)
LightnessImpl(const UInt8AbstractDataStore& data, UInt8AbstractDataStore& outputData, size_t numComp)
: m_ImageData(data)
, m_FlatImageData(outputData)
, m_NumComp(numComp)
Expand All @@ -84,16 +92,16 @@ class LightnessImpl
}

private:
const UInt8Array& m_ImageData;
UInt8Array& m_FlatImageData;
const UInt8AbstractDataStore& m_ImageData;
UInt8AbstractDataStore& m_FlatImageData;
size_t m_NumComp;
};

template <bool BoundsCheckV>
class SingleChannelImpl
{

public:
SingleChannelImpl(const UInt8Array& data, UInt8Array& outputData, size_t numComp, int32_t channel)
SingleChannelImpl(const UInt8AbstractDataStore& data, UInt8AbstractDataStore& outputData, size_t numComp, int32_t channel)
: m_ImageData(data)
, m_FlatImageData(outputData)
, m_NumComp(numComp)
Expand All @@ -110,7 +118,14 @@ class SingleChannelImpl
{
for(size_t i = start; i < end; i++)
{
m_FlatImageData.setValue(i, static_cast<uint8_t>((m_ImageData.at(m_NumComp * i + static_cast<size_t>(m_Channel)))));
if constexpr(BoundsCheckV)
{
m_FlatImageData.setValue(i, m_ImageData.at(m_NumComp * i + static_cast<size_t>(m_Channel)));
}
else
{
m_FlatImageData.setValue(i, m_ImageData[m_NumComp * i + static_cast<size_t>(m_Channel)]);
}
}
}

Expand All @@ -120,8 +135,8 @@ class SingleChannelImpl
}

private:
const UInt8Array& m_ImageData;
UInt8Array& m_FlatImageData;
const UInt8AbstractDataStore& m_ImageData;
UInt8AbstractDataStore& m_FlatImageData;
size_t m_NumComp;
int32_t m_Channel;
};
Expand All @@ -136,11 +151,11 @@ class ParallelWrapper
ParallelWrapper& operator=(ParallelWrapper&&) = delete; // Move Assignment Not Implemented

template <typename T>
static void Run(T impl, size_t totalPoints, typename IParallelAlgorithm::AlgorithmArrays algArrays)
static void Run(T impl, size_t totalPoints, const typename IParallelAlgorithm::AlgorithmStores& algStores)
{
ParallelDataAlgorithm dataAlg;
dataAlg.setRange(0, totalPoints);
dataAlg.requireArraysInMemory(algArrays);
dataAlg.requireStoresInMemory(algStores);
dataAlg.execute(impl);
}

Expand Down Expand Up @@ -180,32 +195,56 @@ Result<> ConvertColorToGrayScale::operator()()
{
break;
}
const auto& inputColorData = m_DataStructure.getDataRefAs<UInt8Array>(arrayPath);
auto& outputGrayData = m_DataStructure.getDataRefAs<UInt8Array>(*outputPathIter);
const auto& inputColorData = m_DataStructure.getDataAs<UInt8Array>(arrayPath)->getDataStoreRef();
auto& outputGrayData = m_DataStructure.getDataAs<UInt8Array>(*outputPathIter)->getDataStoreRef();

auto convType = static_cast<ConversionType>(m_InputValues->ConversionAlgorithm);

size_t comp = inputColorData.getNumberOfComponents();
size_t totalPoints = inputColorData.getNumberOfTuples();

typename IParallelAlgorithm::AlgorithmArrays algArrays;
algArrays.push_back(&inputColorData);
algArrays.push_back(&outputGrayData);
typename IParallelAlgorithm::AlgorithmStores algStores;
algStores.push_back(&inputColorData);
algStores.push_back(&outputGrayData);

switch(convType)
{
case ConversionType::Luminosity:
ParallelWrapper::Run<LuminosityImpl>(LuminosityImpl(inputColorData, outputGrayData, m_InputValues->ColorWeights, comp), totalPoints, algArrays);
if(comp < 3) // Pre-check bounds to try to avoid `.at()`; algorithm hardcoded a component access size of 3
{
// Do bounds check
ParallelWrapper::Run<LuminosityImpl<true>>(LuminosityImpl<true>(inputColorData, outputGrayData, m_InputValues->ColorWeights, comp), totalPoints, algStores);
}
else
{
ParallelWrapper::Run<LuminosityImpl<false>>(LuminosityImpl<false>(inputColorData, outputGrayData, m_InputValues->ColorWeights, comp), totalPoints, algStores);
}
break;
case ConversionType::Average:
ParallelWrapper::Run<LuminosityImpl>(LuminosityImpl(inputColorData, outputGrayData, {0.3333f, 0.3333f, 0.3333f}, comp), totalPoints, algArrays);
if(comp < 3) // Pre-check bounds to try to avoid `.at()`; algorithm hardcoded a component access size of 3
{
// Do bounds check
ParallelWrapper::Run<LuminosityImpl<true>>(LuminosityImpl<true>(inputColorData, outputGrayData, {0.3333f, 0.3333f, 0.3333f}, comp), totalPoints, algStores);
}
else
{
ParallelWrapper::Run<LuminosityImpl<false>>(LuminosityImpl<false>(inputColorData, outputGrayData, {0.3333f, 0.3333f, 0.3333f}, comp), totalPoints, algStores);
}
break;
case ConversionType::Lightness: {
ParallelWrapper::Run<LightnessImpl>(LightnessImpl(inputColorData, outputGrayData, comp), totalPoints, algArrays);
ParallelWrapper::Run<LightnessImpl>(LightnessImpl(inputColorData, outputGrayData, comp), totalPoints, algStores);
break;
}
case ConversionType::SingleChannel:
ParallelWrapper::Run<SingleChannelImpl>(SingleChannelImpl(inputColorData, outputGrayData, comp, m_InputValues->ColorChannel), totalPoints, algArrays);
if(comp * (totalPoints - 1) + m_InputValues->ColorChannel < inputColorData.getSize()) // Pre-check bounds to try to avoid `.at()`
{
// Do bounds check
ParallelWrapper::Run<SingleChannelImpl<false>>(SingleChannelImpl<false>(inputColorData, outputGrayData, comp, m_InputValues->ColorChannel), totalPoints, algStores);
}
else
{
ParallelWrapper::Run<SingleChannelImpl<true>>(SingleChannelImpl<true>(inputColorData, outputGrayData, comp, m_InputValues->ColorChannel), totalPoints, algStores);
}
break;
}
}
Expand Down
37 changes: 35 additions & 2 deletions src/simplnx/Utilities/IParallelAlgorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,37 @@

#include "simplnx/Core/Application.hpp"

namespace
{
// -----------------------------------------------------------------------------
bool CheckStoresInMemory(const nx::core::IParallelAlgorithm::AlgorithmStores& stores)
{
if(stores.empty())
{
return true;
}

for(const auto* storePtr : stores)
{
if(storePtr == nullptr)
{
continue;
}

if(!storePtr->getDataFormat().empty())
{
return false;
}
}

return true;
}
} // namespace

namespace nx::core
{
// -----------------------------------------------------------------------------
bool IParallelAlgorithm::CheckArraysInMemory(const AlgorithmArrays& arrays)
bool detail::CheckArraysInMemory(const nx::core::IParallelAlgorithm::AlgorithmArrays& arrays)
{
if(arrays.empty())
{
Expand Down Expand Up @@ -56,6 +83,12 @@ void IParallelAlgorithm::setParallelizationEnabled(bool doParallel)
// -----------------------------------------------------------------------------
void IParallelAlgorithm::requireArraysInMemory(const AlgorithmArrays& arrays)
{
setParallelizationEnabled(CheckArraysInMemory(arrays));
setParallelizationEnabled(detail::CheckArraysInMemory(arrays));
}

// -----------------------------------------------------------------------------
void IParallelAlgorithm::requireStoresInMemory(const AlgorithmStores& stores)
{
setParallelizationEnabled(::CheckStoresInMemory(stores));
}
} // namespace nx::core
13 changes: 10 additions & 3 deletions src/simplnx/Utilities/IParallelAlgorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "simplnx/Common/Types.hpp"
#include "simplnx/DataStructure/IDataArray.hpp"
#include "simplnx/DataStructure/IDataStore.hpp"
#include "simplnx/simplnx_export.hpp"

#include <vector>
Expand All @@ -12,8 +13,7 @@ class SIMPLNX_EXPORT IParallelAlgorithm
{
public:
using AlgorithmArrays = std::vector<const IDataArray*>;

static bool CheckArraysInMemory(const AlgorithmArrays& arrays);
using AlgorithmStores = std::vector<const IDataStore*>;

IParallelAlgorithm(const IParallelAlgorithm&) = default;
IParallelAlgorithm(IParallelAlgorithm&&) noexcept = default;
Expand All @@ -24,7 +24,7 @@ class SIMPLNX_EXPORT IParallelAlgorithm
* @brief Returns true if parallelization is enabled. Returns false otherwise.
* @return
*/
bool getParallelizationEnabled() const;
[[nodiscard]] bool getParallelizationEnabled() const;

/**
* @brief Sets whether parallelization is enabled.
Expand All @@ -34,6 +34,8 @@ class SIMPLNX_EXPORT IParallelAlgorithm

void requireArraysInMemory(const AlgorithmArrays& arrays);

void requireStoresInMemory(const AlgorithmStores& arrays);

protected:
IParallelAlgorithm();
~IParallelAlgorithm();
Expand All @@ -45,4 +47,9 @@ class SIMPLNX_EXPORT IParallelAlgorithm
bool m_RunParallel = false;
#endif
};

namespace detail
{
bool CheckArraysInMemory(const nx::core::IParallelAlgorithm::AlgorithmArrays& arrays);
}
} // namespace nx::core

0 comments on commit c791078

Please sign in to comment.