Commit aea3cc91 authored by William F Godoy's avatar William F Godoy
Browse files

Non-contiguous memory min max function

parent 2f0dd534
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -29,6 +29,20 @@ namespace helper
 */
size_t GetTotalSize(const Dims &dimensions) noexcept;

/**
 * Populates min and max for a selection region inside
 * @param values
 * @param shape
 * @param start
 * @param count
 * @param min
 * @param max
 */
template <class T>
void GetMinMaxSelection(const T *values, const Dims &shape, const Dims &start,
                        const Dims &count, const bool isRowMajor, T &min,
                        T &max) noexcept;

/**
 * Gets the min and max from a values array of primitive types (not including
 * complex)
+143 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include <algorithm> // std::minmax_element, std::min_element, std::max_element
                     // std::transform
#include <limits>    //std::numeri_limits
#include <thread>

#include "adios2/ADIOSMacros.h"
@@ -25,6 +26,148 @@ namespace adios2
namespace helper
{

template <class T>
void GetMinMaxSelection(const T *values, const Dims &shape, const Dims &start,
                        const Dims &count, const bool isRowMajor, T &min,
                        T &max) noexcept
{
    auto lf_MinMaxRowMajor = [](const T *values, const Dims &shape,
                                const Dims &start, const Dims &count, T &min,
                                T &max) {

        // loop through selection box contiguous part
        const size_t dimensions = shape.size();
        const size_t stride = count.back();
        const size_t startCoord = dimensions - 2;

        Dims currentPoint(start); // current point for contiguous memory
        bool run = true;

        min = std::numeric_limits<T>::max();
        max = std::numeric_limits<T>::min();

        while (run)
        {
            // here copy current linear memory between currentPoint and end
            const size_t startOffset = helper::LinearIndex(
                Dims(shape.size(), 0), shape, currentPoint, true);

            T minStride, maxStride;
            GetMinMax(values + startOffset, stride, minStride, maxStride);

            if (minStride < min)
            {
                min = minStride;
            }
            if (maxStride > max)
            {
                max = maxStride;
            }

            size_t p = startCoord;
            while (true)
            {
                ++currentPoint[p];
                if (currentPoint[p] > start[p] + count[p] - 1)
                {
                    if (p == 0)
                    {
                        run = false; // we are done
                        break;
                    }
                    else
                    {
                        currentPoint[p] = start[p];
                        --p;
                    }
                }
                else
                {
                    break; // break inner p loop
                }
            } // dimension index update
        }     // end while stride loop
    };

    auto lf_MinMaxColumnMajor = [](const T *values, const Dims &shape,
                                   const Dims &start, const Dims &count, T &min,
                                   T &max) {

        // loop through selection box contiguous part
        const size_t dimensions = shape.size();
        const size_t stride = count.front();
        const size_t startCoord = 1;

        Dims currentPoint(start); // current point for contiguous memory
        bool run = true;

        min = std::numeric_limits<T>::max();
        max = std::numeric_limits<T>::min();

        while (run)
        {
            // here copy current linear memory between currentPoint and end
            const size_t startOffset = helper::LinearIndex(
                Dims(shape.size(), 0), shape, currentPoint, false);

            T minStride, maxStride;
            GetMinMax(values + startOffset, stride, minStride, maxStride);

            if (minStride < min)
            {
                min = minStride;
            }
            if (maxStride > max)
            {
                max = maxStride;
            }

            size_t p = startCoord;

            while (true)
            {
                ++currentPoint[p];
                if (currentPoint[p] > start[p] + count[p] - 1)
                {
                    if (p == dimensions - 1)
                    {
                        run = false; // we are done
                        break;
                    }
                    else
                    {
                        currentPoint[p] = start[p];
                        ++p;
                    }
                }
                else
                {
                    break; // break inner p loop
                }
            } // dimension index update

        } // end while stride loop
    };

    if (shape.size() == 1)
    {
        const size_t startOffset =
            helper::LinearIndex(Dims(1, 0), shape, start, isRowMajor);
        const size_t totalSize = helper::GetTotalSize(count);
        GetMinMax(values + startOffset, totalSize, min, max);
        return;
    }

    if (isRowMajor)
    {
        lf_MinMaxRowMajor(values, shape, start, count, min, max);
    }
    else
    {
        lf_MinMaxColumnMajor(values, shape, start, count, min, max);
    }
}

template <class T>
void GetMinMax(const T *values, const size_t size, T &min, T &max) noexcept
{
+11 −0
Original line number Diff line number Diff line
@@ -362,6 +362,17 @@ BP3Serializer::Stats<T> BP3Serializer::GetBPStats(
            helper::GetMinMaxThreads(blockInfo.Data, valuesSize, stats.Min,
                                     stats.Max, m_Threads);
        }
        else
        {
            // TODO: need RowMajor bool
            //            helper::GetMinMaxSelection(blockInfo.Data,
            //            blockInfo.MemoryCount,
            //                                       blockInfo.MemoryStart,
            //                                       blockInfo.Count,
            //                                       true, stats.Min,
            //                                       stats.Max);
        }

        // TODO need to implement minmax for non-contiguous memory
        ProfilerStop("minmax");
    }