Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utility library #2

Open
MathiasMagnus opened this issue Apr 17, 2020 · 0 comments
Open

Utility library #2

MathiasMagnus opened this issue Apr 17, 2020 · 0 comments

Comments

@MathiasMagnus
Copy link
Collaborator

In #1 I touched upon the issue of how to present utilities from the SDK to the users.

The way I imagine the OpenCL SDK hosted by Khronos, is that it provides all the necessary files to compile an OpenCL application (the ICD loader and headers) as well as a utility library which applications could rely on to take care of some tedium in the API.

Consume via CMake

The way I imagined this was to extend the current CMake namespace with the SDK library. Applications consuming both sub-projects may do so via:

find_package(OpenCL 3.0
  REQUIRED
  COMPONENTS
    OpenCL
    SDK
)

add_executable(my_app ${SOURCES})

target_link_libraries(my_app
  PRIVATE
    OpenCL::OpenCL
    OpenCL::SDK
)

Utilities

Here is a short list of things I've grown to use in a few applications of mine.

profiling a la std::chrono

std::cout <<
        "Device (kernel) execution took: " <<
        cl::util::get_duration<CL_PROFILING_COMMAND_START,
                               CL_PROFILING_COMMAND_END,
                               std::chrono::microseconds>(kernel_event).count() <<
        " us." << std::endl;

implementation

namespace cl::util
{
    template <cl_int From, cl_int To, typename Dur = std::chrono::nanoseconds>
    auto get_duration(cl::Event& ev)
    {
        return std::chrono::duration_cast<Dur>(std::chrono::nanoseconds{ ev.getProfilingInfo<To>() - ev.getProfilingInfo<From>() });
    }
}

Iterator-based entry point

This I would like to propose as well for opencl.hpp

std::vector<cl::Platform> platforms(cl::util::Platform::begin(),
                                    cl::util::Platform::end());

implementation

namespace cl::util
{
    namespace Platform
    {
        class PlatformIterator;
        PlatformIterator begin();
        PlatformIterator end();

        cl_uint count()
        {
            cl_int _err = CL_SUCCESS;
            cl_uint _numPlatforms = 0;
            
            _err = clGetPlatformIDs(0, nullptr, &_numPlatforms);
            if (_err != CL_SUCCESS) throw cl::Error{ _err, "clGetPlatformIDs(0, nullptr, &cl_uint)" };

            return _numPlatforms;
        }

        class PlatformIterator
        {
            friend PlatformIterator begin();
            friend PlatformIterator end();

        public:
            typedef std::input_iterator_tag iterator_category;
            typedef cl::Platform value_type;
            typedef std::ptrdiff_t difference_type;
            typedef cl::Platform* pointer;
            typedef cl::Platform reference;

            PlatformIterator& operator++() { ++_curr; return *this; }
            PlatformIterator operator++(int) { auto res = *this; ++_curr; return res; }
            reference operator*() const { return _plats.at(_curr); }
            pointer operator->() const;
            bool operator==(const PlatformIterator& b) const { return _curr == b._curr; }
            bool operator!=(const PlatformIterator& b) const { return _curr != b._curr; }

        private:
            cl_uint _curr;
            std::vector<cl::Platform> _plats;

            PlatformIterator() : PlatformIterator{ 0 } {}
            PlatformIterator(cl_uint curr)
                : _curr{ curr }
            {
                if (_curr != count()) cl::Platform::get(&_plats);
            }
        };

        PlatformIterator begin() { return PlatformIterator{ 0 }; }
        PlatformIterator end() { return PlatformIterator{ count() }; }
    }
}

Obtain executable path

auto kernel_path = cl::util::get_exe_path().parent_path().append("saxpy.cl");
        std::ifstream source_file{ kernel_path };
        if (!source_file.is_open())
            throw std::runtime_error{ std::string{ "Cannot open kernel source: " } + kernel_path.generic_string() };

implementation

// Header //
#if __has_include(<filesystem>)
#include <filesystem>
#elif __has_include(<experimental/filesystem>)
#include <experimental/filesystem>

namespace std {
    namespace filesystem = experimental::filesystem;
}
#else
#error "No STL filesystem support could be detected"
#endif

namespace cl::util
{
    std::filesystem::path get_exe_path();
}

// Source //
#ifdef _WIN32
#include <Windows.h>    //GetModuleFileNameW
#else
#include <limits.h>
#include <unistd.h>     //readlink
#endif

std::filesystem::path cl::util::get_exe_path()
{
#ifdef _WIN32
    wchar_t path[MAX_PATH] = { 0 };
    GetModuleFileNameW(NULL, path, MAX_PATH);
    return path;
#else
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    return std::string(result, (count > 0) ? count : 0);
#endif
}
danieleftodi pushed a commit to danieleftodi/OpenCL-SDK that referenced this issue Jan 9, 2022
* WIP

* Added error handling to context_properties

* Initial Utility and SDK lib docs

* Match definition to declaration

* Fix constraints lifetime

* Explicit narrowing conversion

* Fix lifetime

* Initial NBody sample

* Reduce NBody particle count

* NBody docs

* Add GLM as a dependency

* Don't draw after closing window

* Fix InteropWindow namespace

* Don't call CTOR explicitly

* Simplify includes

* Build SDK libs in correct place

* Hook SDK deps to the correct targerts

* Only install Util headers

* Check for TCLAP alongside other deps

* Only check for sample deps when building them

* Add TCLAP to SDK props

* Build SDK lib only with samples

* Inherit common deps from libSDK

* Modularize Stb detection for non-Vcpkg consumers

* Revamp dependency use

* Install layout overhaul

* Fix CI YAML

* Fix dynamic library dependence in install tree

* Update readme

* Don't test NBody using CTest

* Move image Dockerfiles to OpenCL-SDK

* Remove dead kernel code

* README typo fixes.

* Newline

* Update submodules to point GitHub

* Apply git-format

* CI bump

* Install deps.

* apt update

* Install stb

* Acknolwedge Linux stb install layout

* Fix build path

* Fix vcpkg paths

Co-authored-by: Ivan Siutsou <ivan@streamhpc.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant