diff --git a/libnd4j/blas/CMakeLists.txt b/libnd4j/blas/CMakeLists.txt index a54ad52b4..51a29e522 100755 --- a/libnd4j/blas/CMakeLists.txt +++ b/libnd4j/blas/CMakeLists.txt @@ -336,7 +336,7 @@ elseif(CPU_BLAS) if ("${LIBND4J_ALL_OPS}" AND "${LIBND4J_BUILD_MINIFIER}") message(STATUS "Building minifier...") add_executable(minifier ../minifier/minifier.cpp ../minifier/graphopt.cpp) - target_link_libraries(minifier ${LIBND4J_NAME}static ${MKLDNN_LIBRARIES} ${OPENBLAS_LIBRARIES} ${MKLDNN} ${BLAS_LIBRARIES}) + target_link_libraries(minifier ${LIBND4J_NAME}static ${MKLDNN_LIBRARIES} ${OPENBLAS_LIBRARIES} ${MKLDNN} ${BLAS_LIBRARIES} ${CPU_FEATURES}) endif() if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 4.9) diff --git a/libnd4j/blas/NDArrayFactory.h b/libnd4j/blas/NDArrayFactory.h index 5e979f1d8..bff199d08 100644 --- a/libnd4j/blas/NDArrayFactory.h +++ b/libnd4j/blas/NDArrayFactory.h @@ -108,6 +108,13 @@ namespace nd4j { template static NDArray create(char order, const std::vector &shape, const std::initializer_list& data, nd4j::LaunchContext * context = nd4j::LaunchContext ::defaultContext()); + /** + * This method creates NDArray from .npy file + * @param fileName + * @return + */ + static NDArray fromNpyFile(const char *fileName); + /** * This factory create array from utf8 string * @return NDArray default dataType UTF8 diff --git a/libnd4j/blas/cpu/NDArrayFactory.cpp b/libnd4j/blas/cpu/NDArrayFactory.cpp index 738dccdbe..736452b48 100644 --- a/libnd4j/blas/cpu/NDArrayFactory.cpp +++ b/libnd4j/blas/cpu/NDArrayFactory.cpp @@ -24,11 +24,15 @@ #include #include #include +#include #include #include + + #include +#include namespace nd4j { @@ -688,4 +692,27 @@ template ND4J_EXPORT NDArray NDArrayFactory::create(int16_t* buffer, const char return NDArray( shape, string, dtype, context); } + + NDArray NDArrayFactory::fromNpyFile(const char *fileName) { + auto size = nd4j::graph::getFileSize(fileName); + if (size < 0) + throw std::runtime_error("File doesn't exit"); + + auto pNPY = reinterpret_cast(::numpyFromFile(std::string(fileName))); + + auto nBuffer = reinterpret_cast(::dataPointForNumpy(pNPY)); + auto shape = reinterpret_cast(::shapeBufferForNumpy(pNPY)); + + auto length = shape::length(shape); + int8_t *buffer = nullptr; + nd4j::memory::Workspace *workspace = nullptr; + auto byteLen = length * DataTypeUtils::sizeOfElement(ArrayOptions::dataType(shape)); + + ALLOCATE(buffer, workspace, byteLen, int8_t); + memcpy(buffer, nBuffer, byteLen); + + free(pNPY); + + return NDArray(buffer, shape, LaunchContext::defaultContext(), true); + } } diff --git a/libnd4j/tests_cpu/layers_tests/NDArrayTests2.cpp b/libnd4j/tests_cpu/layers_tests/NDArrayTests2.cpp index 4507086f5..e3dc1aefc 100644 --- a/libnd4j/tests_cpu/layers_tests/NDArrayTests2.cpp +++ b/libnd4j/tests_cpu/layers_tests/NDArrayTests2.cpp @@ -1294,4 +1294,14 @@ TEST_F(NDArrayTest2, test_subarray_followed_by_reshape_1) { // r.printIndexedBuffer("r"); ASSERT_EQ(e, r); +} + +TEST_F(NDArrayTest2, test_numpy_import_1) { + std::string fname("./resources/arr_3,4_float32.npy"); + auto exp = NDArrayFactory::create('c', {3, 4}); + exp.linspace(0); + + auto array = NDArrayFactory::fromNpyFile(fname.c_str()); + + ASSERT_EQ(exp, array); } \ No newline at end of file diff --git a/libnd4j/tests_cpu/resources/arr_3,4_float32.npy b/libnd4j/tests_cpu/resources/arr_3,4_float32.npy new file mode 100644 index 000000000..ead15844c Binary files /dev/null and b/libnd4j/tests_cpu/resources/arr_3,4_float32.npy differ