[arrayfire] 11/248: Initial commit for heterogenous api for ArrayFire backends

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Tue Nov 17 15:53:49 UTC 2015


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch dfsg-clean
in repository arrayfire.

commit 857a6b4b796a15cfa575f38e5505c9eac870c244
Author: pradeep <pradeep at arrayfire.com>
Date:   Tue Aug 25 16:52:36 2015 -0400

    Initial commit for heterogenous api for ArrayFire backends
---
 CMakeLists.txt                  |  7 ++++
 hapi_examples/CMakeLists.txt    | 13 +++++++
 hapi_examples/test.cpp          | 67 +++++++++++++++++++++++++++++++++++
 include/af/defines.h            | 12 +++++++
 include/af/hapi.h               | 21 +++++++++++
 src/api/hapi/CMakeLists.txt     | 39 +++++++++++++++++++++
 src/api/hapi/data.cpp           | 62 +++++++++++++++++++++++++++++++++
 src/api/hapi/device.cpp         | 43 +++++++++++++++++++++++
 src/api/hapi/print.cpp          | 29 ++++++++++++++++
 src/api/hapi/symbol_manager.cpp | 77 +++++++++++++++++++++++++++++++++++++++++
 src/api/hapi/symbol_manager.hpp | 64 ++++++++++++++++++++++++++++++++++
 11 files changed, 434 insertions(+)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ef2a80a..7ba8e38 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,6 +35,8 @@ OPTION(BUILD_SIFT "Build ArrayFire nonfree algorithms" OFF)
 
 MARK_AS_ADVANCED(BUILD_SIFT)
 
+OPTION(BUILD_HETEROGENOUS_API "Build Heterogeneous ArrayFire API" ON)
+
 # Set a default build type if none was specified
 if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
     set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
@@ -168,6 +170,11 @@ IF(${BUILD_OPENCL})
     ADD_SUBDIRECTORY(src/backend/opencl)
 ENDIF()
 
+IF(${BUILD_HETEROGENOUS_API})
+    ADD_SUBDIRECTORY(src/api/hapi)
+    ADD_SUBDIRECTORY(hapi_examples)
+ENDIF()
+
 IF(${BUILD_DOCS})
     ADD_SUBDIRECTORY(docs)
 ENDIF()
diff --git a/hapi_examples/CMakeLists.txt b/hapi_examples/CMakeLists.txt
new file mode 100644
index 0000000..b7e7aea
--- /dev/null
+++ b/hapi_examples/CMakeLists.txt
@@ -0,0 +1,13 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(arrayfire-hapi-examples)
+
+ADD_DEFINITIONS(-std=c++11)
+
+IF(NOT TARGET af)
+    FIND_PACKAGE(ArrayFire REQUIRED)
+    INCLUDE_DIRECTORIES(${ArrayFire_INCLUDE_DIRS})
+ENDIF()
+
+ADD_EXECUTABLE(hapi_test test.cpp)
+
+TARGET_LINK_LIBRARIES(hapi_test af dl)
diff --git a/hapi_examples/test.cpp b/hapi_examples/test.cpp
new file mode 100644
index 0000000..a7ee36c
--- /dev/null
+++ b/hapi_examples/test.cpp
@@ -0,0 +1,67 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <arrayfire.h>
+#include <af/hapi.h>
+#include <cstdio>
+#include <cstdlib>
+#include <vector>
+#include <algorithm>
+
+using namespace af;
+
+std::vector<float> input(100);
+
+
+// Generate a random number between 0 and 1
+// return a uniform number in [0,1].
+double unifRand()
+{
+    return rand() / double(RAND_MAX);
+}
+
+void testBackend()
+{
+    af_info();
+
+    dim_t dims[] = {10, 10, 1, 1};
+
+    af_array A = 0;
+    af_array B = 0;
+
+    af_create_array(&A, &(input.front()), 4, dims, af_dtype::f32);
+    af_print_array(A);
+
+    af_constant(&B, 0.5, 4, dims, af_dtype::f32);
+    af_print_array(B);
+
+    af_release_array(A);
+    af_release_array(B);
+}
+
+int main(int argc, char *argv[])
+{
+    std::generate(input.begin(), input.end(), unifRand);
+
+    af_set_backend(AF_BACKEND_CPU);
+    testBackend();
+
+    af_set_backend(AF_BACKEND_OPENCL);
+    testBackend();
+
+    #ifdef WIN32 // pause in Windows
+    if (!(argc == 2 && argv[1][0] == '-')) {
+        printf("hit [enter]...");
+        fflush(stdout);
+        getchar();
+    }
+    #endif
+
+    return 0;
+}
diff --git a/include/af/defines.h b/include/af/defines.h
index 8587ef3..bc53cff 100644
--- a/include/af/defines.h
+++ b/include/af/defines.h
@@ -149,6 +149,11 @@ typedef enum {
     /// not support graphics
     ///
     AF_ERR_NO_GFX         = 402,
+
+    // 500-599 Errors specific to heterogenous API
+    AF_ERR_LOAD_LIB       = 501,
+    AF_ERR_SYM_LOAD       = 502,
+
     // 900-999 Errors from upstream libraries and runtimes
 
     ///
@@ -316,6 +321,12 @@ typedef enum {
     AF_FIF_RAW          = 34    ///< FreeImage Enum for RAW Camera Image File
 } af_image_format;
 
+typedef enum {
+    AF_BACKEND_CPU,
+    AF_BACKEND_CUDA,
+    AF_BACKEND_OPENCL
+} af_backend;
+
 // Below enum is purely added for example purposes
 // it doesn't and shoudn't be used anywhere in the
 // code. No Guarantee's provided if it is used.
@@ -342,6 +353,7 @@ namespace af
     typedef af_norm_type normType;
     typedef af_ycc_std YCCStd;
     typedef af_image_format imageFormat;
+    typedef af_backend Backend;
 }
 
 #endif
diff --git a/include/af/hapi.h b/include/af/hapi.h
new file mode 100644
index 0000000..f6185a7
--- /dev/null
+++ b/include/af/hapi.h
@@ -0,0 +1,21 @@
+/*******************************************************
+ * Copyright (c) 2014, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#pragma once
+#include <af/defines.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+AFAPI af_err af_set_backend(const af_backend bknd);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/api/hapi/CMakeLists.txt b/src/api/hapi/CMakeLists.txt
new file mode 100644
index 0000000..23f7c8a
--- /dev/null
+++ b/src/api/hapi/CMakeLists.txt
@@ -0,0 +1,39 @@
+
+FILE(GLOB hapi_headers
+    "*.hpp"
+    "*.h")
+
+FILE(GLOB hapi_sources
+    "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
+
+ADD_LIBRARY(af SHARED
+            ${hapi_headers}
+            ${hapi_sources})
+
+IF(${BUILD_CPU})
+    ADD_DEPENDENCIES(af afcpu)
+ENDIF()
+
+IF(${BUILD_CUDA})
+    ADD_DEPENDENCIES(af afcuda)
+ENDIF()
+
+IF(${BUILD_OPENCL})
+    ADD_DEPENDENCIES(af afopencl)
+ENDIF()
+
+SET_TARGET_PROPERTIES(af PROPERTIES
+                      VERSION "${AF_VERSION}"
+                      SOVERSION "${AF_VERSION_MAJOR}")
+
+INSTALL(TARGETS af EXPORT AF DESTINATION "${AF_INSTALL_LIB_DIR}"
+        COMPONENT libraries)
+
+IF(APPLE)
+    INSTALL(SCRIPT "${CMAKE_MODULE_PATH}/osx_install/InstallTool.cmake")
+ENDIF(APPLE)
+
+EXPORT(TARGETS af FILE ArrayFireHAPI.cmake)
+INSTALL(EXPORT AF DESTINATION "${AF_INSTALL_CMAKE_DIR}"
+        COMPONENT cmake
+        FILE ArrayFireHAPI.cmake)
diff --git a/src/api/hapi/data.cpp b/src/api/hapi/data.cpp
new file mode 100644
index 0000000..cc042ef
--- /dev/null
+++ b/src/api/hapi/data.cpp
@@ -0,0 +1,62 @@
+/*******************************************************
+ * Copyright (c) 2014, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <af/array.h>
+#include <af/data.h>
+#include <functional>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <iostream>
+#include "symbol_manager.hpp"
+
+af_err af_create_array(af_array *result, const void * const data,
+                       const unsigned ndims, const dim_t * const dims,
+                       const af_dtype type)
+{
+    af_err errCode = AF_SUCCESS;
+    try {
+        AFSymbolManager& symbolManager = AFSymbolManager::getInstance();
+        errCode = symbolManager.call("af_create_array", result, data, ndims, dims, type);
+    } catch(std::logic_error &e) {
+        // FIXME: remove std::cerr
+        std::cerr<<e.what()<<std::endl;
+        errCode = AF_ERR_SYM_LOAD;
+    }
+    return errCode;
+}
+
+af_err af_constant(af_array *result, const double value,
+                   const unsigned ndims, const dim_t * const dims,
+                   const af_dtype type)
+{
+    af_err errCode = AF_SUCCESS;
+    try {
+        AFSymbolManager& symbolManager = AFSymbolManager::getInstance();
+        errCode = symbolManager.call("af_constant", result, value, ndims, dims, type);
+    } catch(std::logic_error &e) {
+        // FIXME: remove std::cerr
+        std::cerr<<e.what()<<std::endl;
+        errCode = AF_ERR_SYM_LOAD;
+    }
+    return errCode;
+}
+
+af_err af_release_array(af_array arr)
+{
+    af_err errCode = AF_SUCCESS;
+    try {
+        AFSymbolManager& symbolManager = AFSymbolManager::getInstance();
+        errCode = symbolManager.call("af_release_array", arr);
+    } catch(std::logic_error &e) {
+        // FIXME: remove std::cerr
+        std::cerr<<e.what()<<std::endl;
+        errCode = AF_ERR_SYM_LOAD;
+    }
+    return errCode;
+}
diff --git a/src/api/hapi/device.cpp b/src/api/hapi/device.cpp
new file mode 100644
index 0000000..dc4de07
--- /dev/null
+++ b/src/api/hapi/device.cpp
@@ -0,0 +1,43 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <af/hapi.h>
+#include <af/device.h>
+#include <functional>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <iostream>
+#include "symbol_manager.hpp"
+
+af_err af_set_backend(const af_backend bknd)
+{
+    af_err errCode = AF_SUCCESS;
+    try {
+        AFSymbolManager::getInstance().setBackend(bknd);
+    } catch(std::logic_error &e) {
+        // FIXME: remove std::cerr
+        std::cerr<<e.what()<<std::endl;
+        errCode = AF_ERR_LOAD_LIB;
+    }
+    return errCode;
+}
+
+af_err af_info()
+{
+    af_err errCode = AF_SUCCESS;
+    try {
+        AFSymbolManager& symbolManager = AFSymbolManager::getInstance();
+        errCode = symbolManager.call("af_info");
+    } catch(std::logic_error &e) {
+        // FIXME: remove std::cerr
+        std::cerr<<e.what()<<std::endl;
+        errCode = AF_ERR_SYM_LOAD;
+    }
+    return errCode;
+}
diff --git a/src/api/hapi/print.cpp b/src/api/hapi/print.cpp
new file mode 100644
index 0000000..3eb28cd
--- /dev/null
+++ b/src/api/hapi/print.cpp
@@ -0,0 +1,29 @@
+/*******************************************************
+ * Copyright (c) 2014, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <af/util.h>
+#include <functional>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <iostream>
+#include "symbol_manager.hpp"
+
+af_err af_print_array(const af_array arr)
+{
+    af_err errCode = AF_SUCCESS;
+    try {
+        AFSymbolManager& symbolManager = AFSymbolManager::getInstance();
+        errCode = symbolManager.call("af_print_array", arr);
+    } catch(std::logic_error &e) {
+        // FIXME: remove std::cerr
+        std::cerr<<e.what()<<std::endl;
+        errCode = AF_ERR_SYM_LOAD;
+    }
+    return errCode;
+}
diff --git a/src/api/hapi/symbol_manager.cpp b/src/api/hapi/symbol_manager.cpp
new file mode 100644
index 0000000..ce5bf18
--- /dev/null
+++ b/src/api/hapi/symbol_manager.cpp
@@ -0,0 +1,77 @@
+/*******************************************************
+ * Copyright (c) 2014, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include "symbol_manager.hpp"
+
+AFSymbolManager& AFSymbolManager::getInstance()
+{
+    static AFSymbolManager symbolManager;
+    return symbolManager;
+}
+
+AFSymbolManager::AFSymbolManager()
+    : isCPULoaded(false), isCUDALoaded(false), isOCLLoaded(false)
+{
+    cpuHandle = dlopen("libafcpu.so", RTLD_LAZY);
+    if (cpuHandle) {
+        isCPULoaded = true;
+        activeHandle = cpuHandle;
+    }
+    cudaHandle = dlopen("libafcuda.so", RTLD_LAZY);
+    if (cudaHandle) {
+        isCUDALoaded = true;
+        activeHandle = cudaHandle;
+    }
+    oclHandle = dlopen("libafopencl.so", RTLD_LAZY);
+    if (oclHandle) {
+        isOCLLoaded = true;
+        activeHandle = oclHandle;
+    }
+}
+
+AFSymbolManager::~AFSymbolManager()
+{
+    if (isCPULoaded) {
+        dlclose(cpuHandle);
+        isCPULoaded = false;
+    }
+    if (isCUDALoaded) {
+        dlclose(cudaHandle);
+        isCUDALoaded = false;
+    }
+    if (isOCLLoaded) {
+        dlclose(oclHandle);
+        isOCLLoaded = false;
+    }
+}
+
+void AFSymbolManager::setBackend(af::Backend bknd)
+{
+    activeBknd = bknd;
+    switch (activeBknd) {
+        case af::Backend::AF_BACKEND_CPU:
+            if(isCPULoaded)
+                activeHandle = cpuHandle;
+            else
+                throw std::logic_error("can't load afcpu library");
+            break;
+        case af::Backend::AF_BACKEND_CUDA:
+            if(isCUDALoaded)
+                activeHandle = cudaHandle;
+            else
+                throw std::logic_error("can't load afcuda library");
+            break;
+        case af::Backend::AF_BACKEND_OPENCL:
+            if(isOCLLoaded)
+                activeHandle = oclHandle;
+            else
+                throw std::logic_error("can't load afopencl library");
+            break;
+    }
+}
diff --git a/src/api/hapi/symbol_manager.hpp b/src/api/hapi/symbol_manager.hpp
new file mode 100644
index 0000000..eea8f38
--- /dev/null
+++ b/src/api/hapi/symbol_manager.hpp
@@ -0,0 +1,64 @@
+/*******************************************************
+ * Copyright (c) 2014, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <af/defines.h>
+#include <functional>
+#include <string>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+class AFSymbolManager {
+    public:
+        static AFSymbolManager& getInstance();
+
+        ~AFSymbolManager();
+
+        void setBackend(af::Backend bnkd);
+
+        template<typename... CalleeArgs>
+        af_err call(const char* symbolName, CalleeArgs... args) {
+            using std::string;
+            using std::logic_error;
+
+            void* const handle = dlsym(activeHandle, symbolName);
+
+            if (!handle) {
+                char* const error = dlerror();
+                if (error) {
+                    throw logic_error("can't find symbol: "+string(symbolName)+" - "+error);
+                }
+            }
+
+            std::function<af_err (CalleeArgs...)> callee = reinterpret_cast<af_err (*)(CalleeArgs...)>(handle);
+
+            return callee(args...);
+        }
+
+    protected:
+        AFSymbolManager();
+
+        // Following two declarations are required to
+        // avoid copying accidental copy/assignment
+        // of instance returned by getInstance to other
+        // variables
+        AFSymbolManager(AFSymbolManager const&);
+        void operator=(AFSymbolManager const&);
+
+    private:
+        bool isCPULoaded;
+        bool isCUDALoaded;
+        bool isOCLLoaded;
+
+        void* cpuHandle;
+        void* cudaHandle;
+        void* oclHandle;
+
+        af::Backend activeBknd;
+        void* activeHandle;
+};

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/arrayfire.git



More information about the debian-science-commits mailing list