How do I know,armadillo is working with openblas on my ARM? - armadillo

How do I know,armadillo is working with openblas on my ARM?
Background
I am writing a program with armadillo, and I install openblas, and using cross compiler to compile it. I wish program with armadillo and openblas is faster than with only armadillo. But they running the same time.
So, on my armv7 board ,how do I know armadillo is working with openblas?
Environment
PC:ubuntu16.04
cross compiler: arm-linux-g++
borad: ARM v7
Compiler command:
only with armadillo:
arm-linux-g++ -mtune=cortex-a7 -std=c++11 -I/home/sgks/SGKS6802_LinuxSDK/sdk_build/system/01_software/armadillo-8.100.0_install/include -L/opt/sgks/rootfs/usr/lib -L/home/sgks/SGKS6802_LinuxSDK/sdk_build/system/01_software/armadillo-8.100.0_install/lib -o ./cmake-build-debug/armadillo_test ./main.cpp -larmadillo -O3
2. with armadillo and openblas:
arm-linux-g++ -mtune=cortex-a7 -std=c++11 -I/home/sgks/SGKS6802_LinuxSDK/sdk_build/system/01_software/armadillo-8.100.0_install/include -I/home/sgks/SGKS6802_LinuxSDK/sdk_build/system/01_software/OpenBLAS-0.2.20-install-arm/include -L/home/sgks/SGKS6802_LinuxSDK/sdk_build/system/01_software/armadillo-8.100.0_install/lib -L/home/sgks/SGKS6802_LinuxSDK/sdk_build/system/01_software/OpenBLAS-0.2.20-install-arm/lib -o ./cmake-build-debug/armadillo_test ./main.cpp -DARMA_DONT_USE_WRAPPER -lopenblas -O3
test code:
`
include
include
using namespace arma;
int main()
{
clock_t start, stop;
double dur;
fmat weigth_layer1(2801, 2642,fill::randu);
fmat weigth_layer2(2643, 2645, fill::randu);
fmat weigth_layer3(2646, 2527, fill::randu);
fmat weigth_layer4(2528, 607, fill::randu);
fmat input(1, 2801, fill::randu);
fmat layer1_output(1,2643);
fmat layer2_output(1,2646);
fmat layer3_output(1,2528);
fmat layer4_output(1,607);
//************************* layer1 *************************
start = clock();
layer1_output(0,span(0,2641)) = input * weigth_layer1;
layer1_output(0,2642) = 1.0; //bias
layer1_output.elem(find(layer1_output < 0 )) -= layer1_output.elem(find(layer1_output < 0 )); //Relu
cout << "layer1: " << layer1_output.n_cols << endl;
//************************* layer2 *************************
layer2_output(0,span(0,2644)) = layer1_output * weigth_layer2;
layer2_output(0,2645) = 1.0; //bias
cout << "layer2: " << layer2_output.n_cols << endl;
layer2_output.elem(find(layer2_output < 0 )) -= layer2_output.elem(find(layer2_output < 0 )); //Relu
//************************* layer3 *************************
layer3_output(0,span(0,2526)) = layer2_output * weigth_layer3;
layer3_output(0,2527) = 1.0;
cout << "layer3: " << layer3_output.n_cols << endl;
layer3_output.elem(find(layer3_output < 0 )) -= layer3_output.elem(find(layer3_output < 0 )); //Relu
//************************* layer4 *************************
layer4_output = layer3_output * weigth_layer4;
cout << "layer4: " << layer4_output.n_cols << endl;
stop = clock();
dur = stop - start;
printf("time : %f\n", dur / CLOCKS_PER_SEC);
return 0;
}
`
PS:code format is wrong, sry for that, stackoverflow doesnt support markdown?

If your OpenBlas is installed correctly and the lib path is correct it should be the one used. You can view the config in Armadillo:
arma::arma_config cfg;
if( cfg.blas)
std::cout << "BLAS enabled: "<< std::endl;
Another way to test is to disable BLAS when you compile and compare the performance (in this case it will use an emulated function). NB! Add this define before you include armadillo.
#define ARMA_DONT_USE_BLAS
#include <armadillo>

you can also check the armadillo library file if it is referencing openblas: for example this is my output by using the ldd command :
ldd /usr/lib/libarmadillo.so
linux-vdso.so.1 (0x0000007f9fe80000)
libblas.so.3 => /usr/lib/aarch64-linux-gnu/libblas.so.3 (0x0000007f9fdb0000)
liblapack.so.3 => /usr/lib/aarch64-linux-gnu/liblapack.so.3 (0x0000007f9f8d4000)
libarpack.so.2 => /usr/lib/aarch64-linux-gnu/libarpack.so.2 (0x0000007f9f884000)
libsuperlu.so.5 => /usr/lib/aarch64-linux-gnu/libsuperlu.so.5 (0x0000007f9f81c000)
libstdc++.so.6 => /usr/lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000007f9f689000)
libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000007f9f5cf000)
libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000007f9f5ab000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000007f9f452000)
libopenblas.so.0 => /usr/lib/aarch64-linux-gnu/libopenblas.so.0 (0x0000007f9ed8a000)
/lib/ld-linux-aarch64.so.1 (0x0000007f9fe55000)
libgfortran.so.4 => /usr/lib/aarch64-linux-gnu/libgfortran.so.4 (0x0000007f9ec86000)
libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0 (0x0000007f9ec5a000)

Related

triSYCL throws non_cl_error, when tricycle::device::~device is called

I'm trying to run a parallel for loop with triSYCL. This is my code:
#define TRISYCL_OPENCL
#define OMP_NUM_THREADS 8
#define BOOST_COMPUTE_USE_CPP11
//standart libraries
#include <iostream>
#include <functional>
//deps
#include "CL/sycl.hpp"
struct Color
{
float r, g, b, a;
friend std::ostream& operator<<(std::ostream& os, const Color& c)
{
os << "(" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ")";
return os;
}
};
struct Vertex
{
float x, y;
Color color;
friend std::ostream& operator<<(std::ostream& os, const Vertex& v)
{
os << "x: " << v.x << ", y: " << v.y << ", color: " << v.color;
return os;
}
};
template<typename T>
T mapNumber(T x, T a, T b, T c, T d)
{
return (x - a) / (b - a) * (d - c) + c;
}
int windowWidth = 640;
int windowHeight = 720;
int main()
{
auto exception_handler = [](cl::sycl::exception_list exceptions) {
for (std::exception_ptr const& e : exceptions)
{
try
{
std::rethrow_exception(e);
} catch (cl::sycl::exception const& e)
{
std::cout << "Caught asynchronous SYCL exception: " << e.what() << std::endl;
}
}
};
cl::sycl::default_selector defaultSelector;
cl::sycl::context context(defaultSelector, exception_handler);
cl::sycl::queue queue(context, defaultSelector, exception_handler);
auto* pixelColors = new Color[windowWidth * windowHeight];
{
cl::sycl::buffer<Color, 2> color_buffer(pixelColors, cl::sycl::range < 2 > {(unsigned long) windowWidth,
(unsigned long) windowHeight});
cl::sycl::buffer<int, 1> b_windowWidth(&windowWidth, cl::sycl::range < 1 > {1});
cl::sycl::buffer<int, 1> b_windowHeight(&windowHeight, cl::sycl::range < 1 > {1});
queue.submit([&](cl::sycl::handler& cgh) {
auto color_buffer_acc = color_buffer.get_access<cl::sycl::access::mode::write>(cgh);
auto width_buffer_acc = b_windowWidth.get_access<cl::sycl::access::mode::read>(cgh);
auto height_buffer_acc = b_windowHeight.get_access<cl::sycl::access::mode::read>(cgh);
cgh.parallel_for<class init_pixelColors>(
cl::sycl::range<2>((unsigned long) width_buffer_acc[0], (unsigned long) height_buffer_acc[0]),
[=](cl::sycl::id<2> index) {
color_buffer_acc[index[0]][index[1]] = {
mapNumber<float>(index[0], 0.f, width_buffer_acc[0], 0.f, 1.f),
mapNumber<float>(index[1], 0.f, height_buffer_acc[0], 0.f, 1.f),
0.f,
1.f};
});
});
std::cout << "cl::sycl::queue check - selected device: "
<< queue.get_device().get_info<cl::sycl::info::device::name>() << std::endl;
}//here the error appears
delete[] pixelColors;
return 0;
}
I'm building it with this CMakeLists.txt file:
cmake_minimum_required(VERSION 3.16.2)
project(acMandelbrotSet_stackoverflow)
set(CMAKE_CXX_STANDARD 17)
set(SRC_FILES
path/to/main.cpp
)
find_package(OpenCL REQUIRED)
set(Boost_INCLUDE_DIR path/to/boost)
include_directories(${Boost_INCLUDE_DIR})
include_directories(path/to/SYCL/include)
set(LIBS PRIVATE ${Boost_LIBRARIES} OpenCL::OpenCL)
add_executable(${PROJECT_NAME} ${SRC_FILES})
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX _d)
target_link_libraries(${PROJECT_NAME} ${LIBS})
When I try to run it, I get this message: libc++abi.dylib: terminating with uncaught exception of type trisycl::non_cl_error from path/to/SYCL/include/triSYCL/command_group/detail/task.hpp line: 278 function: trisycl::detail::task::get_kernel, the message was: "Cannot use an OpenCL kernel in this context".
I've tried to create a lambda of mapNumber in the kernel but that didn't make any difference. I've also tried to use this before the end of the scope to catch errors:
try
{
queue.wait_and_throw();
} catch (cl::sycl::exception const& e)
{
std::cout << "Caught synchronous SYCL exception: " << e.what() << std::endl;
}
but nothing was printed to the console except the error from before. And I've also tried to make an event of the queue.submit call and then call event.wait() before the end of the scope but again the exact same output.
Does any body have an idea what else I could try?
The problem is that triSYCL is a research project looking deeper at some aspects of SYCL while not providing a global generic SYCL support for an end-user. I have just clarified this on the README of the project. :-(
Probably the problem here is that the OpenCL SPIR kernel has not been generated.
So you need to first compile the specific (old) Clang & LLVM from triSYCL https://github.com/triSYCL/triSYCL/blob/master/doc/architecture.rst#trisycl-architecture-for-accelerator. But unfortunately there is no simple Clang driver to use all the specific Clang & LLVM to generate the kernels from the SYCL source. Right know it is done with some ad-hoc awful Makefiles (look around https://github.com/triSYCL/triSYCL/blob/master/tests/Makefile#L360) and, even if you can survive to this, you might encounter some bugs...
The good news is now there are several other implementations of SYCL which are quite easier to use, quite more complete and quite less buggy! :-) Look at ComputeCpp, DPC++ and hipSYCL for example.

GStreamer-CRITICAL **: gst_element_get_state: assertion 'GST_IS_ELEMENT (element)' failed error in Opencv

Am trying to open the web camera through GSTREAMER API using Opencv on windows, but am getting
this error at runtime
GStreamer-CRITICAL **: gst_element_get_state: assertion 'GST_IS_ELEMENT (element)' failed
OpenCV | GStreamer warning: GStreamer: unable to query pipeline state
Below is code am running
VideoCapture capture(0,CAP_GSTREAMER);
if (capture.isOpened()) {
std::cout << "Camera 0 via " << capture.getBackendName() << " backend" << std::endl;
std::cout << "Frame width: " << capture.get(CAP_PROP_FRAME_WIDTH) << std::endl;
std::cout << " height: " << capture.get(CAP_PROP_FRAME_HEIGHT) << std::endl;
std::cout << "Capturing FPS: " << capture.get(CAP_PROP_FPS) << std::endl;
}
However camera is working fine with Gstreamer command
gst-launch-1.0.exe -v ksvideosrc device-index=0 ! autovideosink
I have built OpenCV4.0 with GStreamer enabled, what exactly missing element here and is there a fix for this?
Try the below code:
const char* pipeline= "ksvideosrc device-index=0 ! autovideoconvert ! appsink";
int cap_id = CAP_GSTREAMER;
VideoCapture cap( pipeline, cap_id);

Why does returning an element of a copied Matrix3d result in incorrect output when using Clang 3.9?

Compiling the following example with -O2 on Clang 3.9 results in the reproFunction returning garbage (1.9038e+185) when called in main:
Code
double reproFunction(const Eigen::Matrix3d& R_in)
{
const Eigen::Matrix3d R = R_in;
Eigen::Matrix3d Q = R.cwiseAbs();
if(R(1,2) < 2) {
Eigen::Vector3d n{0, 1, R(1, 2)};
double s2 = R(1,2);
s2 /= n.norm();
}
return R(1, 2);
}
int main() {
Eigen::Matrix3d R;
R = Eigen::Matrix3d::Zero(3,3);
// This fails - reproFunction(R) returns 0
R(1, 2) = 0.7;
double R12 = reproFunction(R);
bool are_they_equal = (R12 == R(1,2));
std::cout << "R12 == R(1,2): " << are_they_equal << std::endl;
std::cout << "R12: " << R12 << std::endl;
std::cout << "R(1, 2): " << R(1, 2) << std::endl;
}
Output
R12 == R(1,2): 0
R12: 1.9036e+185
R(1, 2): 0.7
reproFunction, initializes R (which is const) by assignment from R_in. It returns R(1, 2). Between the assignment and the return, reproFunction uses R in several operations, but none of them should be able to change R. Removing any of those operations results in reproFunction returning the correct value.
This behavior does not appear in any of the following cases:
The program is compiled with Clang 3.5, Clang 4.0,or g++-5.4.
The optimization level is -O1 or lower
Eigen 3.2.10 is used instead of Eigen 3.3.3
Now the question: Is this behavior due to a bug I've missed in the code above, a bug in Eigen 3.3.3, or a bug in Clang 3.9?
A self-contained reproduction example can be found at https://github.com/avalenzu/eigen-clang-weirdness.
I could reproduce this with clang 3.9, but not with clang 3.8. I bisected the issue on Eigen's side to this commit from 2016-05-24 21:54:
Bug 256: enable vectorization with unaligned loads/stores. This concerns all architectures and all sizes. This new behavior can be disabled by defining EIGEN_UNALIGNED_VECTORIZE=0
That commit enables vectorized operations on unaligned data.
I still think, this is a bug in clang, but you can work-around it by compiling with
-D EIGEN_UNALIGNED_VECTORIZE=0
Also, Eigen could be 'fixed' by automatically disabling this feature if clang 3.9 is detected as compiler.

implications of using _mm_shuffle_ps on integer vector

SSE intrinsics includes _mm_shuffle_ps xmm1 xmm2 immx which allows one to pick 2 elements from xmm1 concatenated with 2 elements from xmm2. However this is for floats, (implied by the _ps , packed single). However if you cast your packed integers __m128i, then you can use _mm_shuffle_ps as well:
#include <iostream>
#include <immintrin.h>
#include <sstream>
using namespace std;
template <typename T>
std::string __m128i_toString(const __m128i var) {
std::stringstream sstr;
const T* values = (const T*) &var;
if (sizeof(T) == 1) {
for (unsigned int i = 0; i < sizeof(__m128i); i++) {
sstr << (int) values[i] << " ";
}
} else {
for (unsigned int i = 0; i < sizeof(__m128i) / sizeof(T); i++) {
sstr << values[i] << " ";
}
}
return sstr.str();
}
int main(){
cout << "Starting SSE test" << endl;
cout << "integer shuffle" << endl;
int A[] = {1, -2147483648, 3, 5};
int B[] = {4, 6, 7, 8};
__m128i pC;
__m128i* pA = (__m128i*) A;
__m128i* pB = (__m128i*) B;
*pA = (__m128i)_mm_shuffle_ps((__m128)*pA, (__m128)*pB, _MM_SHUFFLE(3, 2, 1 ,0));
pC = _mm_add_epi32(*pA,*pB);
cout << "A[0] = " << A[0] << endl;
cout << "A[1] = " << A[1] << endl;
cout << "A[2] = " << A[2] << endl;
cout << "A[3] = " << A[3] << endl;
cout << "B[0] = " << B[0] << endl;
cout << "B[1] = " << B[1] << endl;
cout << "B[2] = " << B[2] << endl;
cout << "B[3] = " << B[3] << endl;
cout << "pA = " << __m128i_toString<int>(*pA) << endl;
cout << "pC = " << __m128i_toString<int>(pC) << endl;
}
Snippet of relevant corresponding assembly (mac osx, macports gcc 4.8, -march=native on an ivybridge CPU):
vshufps $228, 16(%rsp), %xmm1, %xmm0
vpaddd 16(%rsp), %xmm0, %xmm2
vmovdqa %xmm0, 32(%rsp)
vmovaps %xmm0, (%rsp)
vmovdqa %xmm2, 16(%rsp)
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
....
Thus it seemingly works fine on integers, which I expected as the registers are agnostic to types, however there must be a reason why the docs say that this instruction is only for floats. Does someone know any downsides, or implications I have missed?
There is no equivalent to _mm_shuffle_ps for integers. To achieve the same effect in this case you can do
SSE2
*pA = _mm_shuffle_epi32(_mm_unpacklo_epi32(*pA, _mm_shuffle_epi32(*pB, 0xe)),0xd8);
SSE4.1
*pA = _mm_blend_epi16(*pA, *pB, 0xf0);
or change to the floating point domain like this
*pA = _mm_castps_si128(
_mm_shuffle_ps(_mm_castsi128_ps(*pA),
_mm_castsi128_ps(*pB), _MM_SHUFFLE(3, 2, 1 ,0)));
But changing domains may incur bypass latency delays on some CPUs. Keep in mind that according to Agner
The bypass delay is important in long dependency chains where latency is a bottleneck, but
not where it is throughput rather than latency that matters.
You have to test your code and see which method above is more efficient.
Fortunately, on most Intel/AMD CPUs, there is usually no penalty for using shufps between most integer-vector instructions. Agner says:
For example, I found no delay when mixing PADDD and SHUFPS [on Sandybridge].
Nehalem does have 2 bypass-delay latency to/from SHUFPS, but even then a single SHUFPS is often still faster than multiple other instructions. Extra instructions have latency, too, as well as costing throughput.
The reverse (integer shuffles between FP math instructions) is not as safe:
In Agner Fog's microarchitecture on page 112 in Example 8.3a, he shows that using PSHUFD (_mm_shuffle_epi32) instead of SHUFPS (_mm_shuffle_ps) when in the floating point domain causes a bypass delay of four clock cycles. In Example 8.3b he uses SHUFPS to remove the delay (which works in his example).
On Nehalem there are actually five domains. Nahalem seems to be the most effected (the bypass delays did not exist before Nahalem). On Sandy Bridge the delays are less significant. This is even more true on Haswell. In fact on Haswell Agner said he found no delays between SHUFPS or PSHUFD (see page 140).

OpenCV line detection and extraction using ios

Hi i am using opencv for the line detection in ios. This is for my final year project. I want to upload the image of ecg and then extract the line from this for that i have used the opencv and sucessfuly i have extracted the line but now i want to save the line and facing much problem in that can anyone help me or any tutorial ?
I wrote something quickly, I think it can help you:
void write_lines_to_file ( string file_name, vector<vector<Point> > lines )
{
FileStorage fs ( file_name, FileStorage::WRITE );
fs << "lines" << "[";
for ( unsigned int i = 0; i < lines.size(); i++ )
{
// I've assumed each line is a vector< Point >, in index [0] the head and index [1] the tail.
fs << "{:" << "x1" << lines[i].at ( 0 ).x << "y1" << lines[i].at ( 0 ).y << "x2" << lines[i].at ( 1 ).x << "y2" << lines[i].at ( 1 ).y << "}";
}
fs.release();
}
I didn't test it and I made my own assumptions, so please be cautious when you want to use it.

Resources