What are XCode 8 Environment Variables to run Intel Threading Building Blocks - c++

I installed the Intel Threading Building Blocks. I am unable to set the environment variables for XCode (lib and include path).
To start with I want to write a simple parallel_for program, I am not able to add even the namespace tbb in my program.
Can anyone please help?
enter image description here

Thats pretty straightforward: best way to install it:
brew install tbb
Requires Homebrew, which is highly recommended for any Mac user wanting to use various open source tools.
Adjust 3 project settings
After that do brew info tbb to see the installation directory, in my case
/usr/local/Cellar/tbb/2017_U7
wich results in
/usr/local/Cellar/tbb/2017_U7/include/
/usr/local/Cellar/tbb/2017_U7/lib/
for the respective project settings, Header Search Paths and Library Search Paths.
In Other Linker Flags enter -ltbb and there you are.
Test code example
I´ve verified this example with the aforementioned settings in Xcode 8.3
#include "tbb/parallel_for.h"
#include "tbb/task_scheduler_init.h"
#include <iostream>
#include <vector>
struct mytask {
mytask(size_t n)
:_n(n)
{}
void operator()() {
for (int i=0;i<1000000;++i) {} // Deliberately run slow
std::cerr << "[" << _n << "]";
}
size_t _n;
};
int main(int,char**) {
//tbb::task_scheduler_init init; // Automatic number of threads
tbb::task_scheduler_init init(tbb::task_scheduler_init::default_num_threads()); // Explicit number of threads
std::vector<mytask> tasks;
for (int i=0;i<1000;++i)
tasks.push_back(mytask(i));
tbb::parallel_for(
tbb::blocked_range<size_t>(0,tasks.size()),
[&tasks](const tbb::blocked_range<size_t>& r) {
for (size_t i=r.begin();i<r.end();++i) tasks[i]();
}
);
std::cerr << std::endl;
return 0;
}

Related

Intel MKL ERROR: Parameter 7 was incorrect on entry to DGELSD when including both Armadillo and Open3D in cpp

I am working on a cpp-project based on Open3D and armadillo on Ubuntu18.04. After adding Open3D::Open3D to linked libraries, some functions from armadillo like arma::inv(A) and arma::solve(X, A, B) that requires Intel MKL don't work and output error message like
"Intel MKL ERROR: Parameter 7 was incorrect on entry to DGELSD".
I've built a standalone program running linear regression that only calls functions in armadillo, but still when I include Open3D in CMakeLists, the program fails with the same error. I am wondering is there any compile flag I should specify when building Open3D, or any possible reason for it cause?
CPP program:
#include <iostream>
#include <armadillo>
#include <unordered_map>
#include <utility>
using namespace std;
using namespace arma;
using namespace std::chrono;
#define AVG_LEN (5ULL)
int main(int argc, char const *argv[])
{
std::unordered_map<std::string, std::pair<size_t, arma::dmat::fixed<AVG_LEN, 3ULL>>> upload_info;
upload_info["A1b"].second.fill(1.0);
auto it = upload_info.find("A1b");
for (int i=0; i<AVG_LEN; ++i) {
it->second.second(i, 0) = i*2;
it->second.second(i, 2) = i+10;
it->second.first++;
}
arma::vec2 X;
arma::dmat::fixed<AVG_LEN, 3ULL> info(it->second.second);
bool status = arma::solve(X, info.cols(0, 1), info.col(2));
if (status)
cout << "X: \n" << X << endl;
return 0;
}
Without including Open3D::Open3D in target_link_libraries, the output is correct as
X:
0.5000
10.0000
But after including that, it just outputs an error message
Intel MKL ERROR: Parameter 7 was incorrect on entry to DGELSD.
I am using Ubuntu 18.04 and Open3D 0.16.1. I build Open3D from source by
cmake -DBUILD_SHARED_LIBS=OFF \
-DBUILD_GUI=OFF -DBUILD_WEBRTC=OFF -DBUILD_PYTHON_MODULE=OFF \
-DGLIBCXX_USE_CXX11_ABI=ON -DWITH_OPENMP=ON \
-DCMAKE_INSTALL_PREFIX=$O3D_INSTALL_DIR ..
Additional information
Armadillo can be easily installed by apt-get install -y liblapack-dev libarmadillo-dev, it uses Blas to accelerate computation. I include Open3d in CMakeLists by
foreach(_target
demo) #
add_executable(${_target} "${_target}.cpp")
target_link_libraries(${_target} Open3D::Open3D
${ARMADILLO_LIBRARIES})
endforeach()
Finally resolved by setting -DBUILD_SHARED_LIBS=ON

How do I properly include files from the NVIDIA C++ standard library?

I was trying to use shared pointers in CUDA by using NVIDIA's version of the C++ standard library. So tried to include <cuda/std/detail/libcxx/include/memory>. I got some errors. One of them includes cannot open source file with <__config> and <__functional_base>. Those files were clearly in the directory. It's like visual studios acts like those files don't exist even though they do. Another error I get is linkage specification is incompatible with previous "" with <cmath>.
I did little digging. I found out that cannot open source file is apparent with every non-header file that starts with _ in cuda/std/detail/libcxx/include/. It is like Visual Studio somehow acts like those files don't exist despite being clearly located in the additional include directories. Furthermore, when I type cuda/std/detail/libcxx/include/, IntelliSense won't find these files. If I can get visual studio to recognize those files, I can properly include any files in NVIDIA's version of standard library.
The first thing to understand is that CUDA doesn't have a C++ standard library. What you are referring to is the libcu++, which is an extremely bare bones heterogenous reimplementation of a tiny subset of what is defined in the C++ standard library. You can use whatever is defined in libcu++ (and that is not much, it is a very incomplete implementation) as follows:
Prepend the local path cuda/std/ to whatever standard library header you are using to substitute the import from the native host C++ standard library to libcu++
Change the namespace from std to cuda::std
compile using nvcc
As a simple example:
$ cat atomics.cpp
#include <iostream> // std::cout
#include <cuda/std/atomic> // cuda::std::atomic, cuda::std::atomic_flag, ATOMIC_FLAG_INIT
#include <thread> // std::thread, std::this_thread::yield
#include <vector> // std::vector
cuda::std::atomic<bool> ready (false);
cuda::std::atomic_flag winner = ATOMIC_FLAG_INIT;
void count1m (int id) {
while (!ready) { std::this_thread::yield(); } // wait for the ready signal
for (volatile int i=0; i<1000000; ++i) {} // go!, count to 1 million
if (!winner.test_and_set()) { std::cout << "thread #" << id << " won!\n"; }
};
int main ()
{
std::vector<std::thread> threads;
std::cout << "spawning 10 threads that count to 1 million...\n";
for (int i=1; i<=10; ++i) threads.push_back(std::thread(count1m,i));
ready = true;
for (auto& th : threads) th.join();
return 0;
}
$ nvcc -std=c++11 -o atomics atomics.cpp -lpthread
$ ./atomics
spawning 10 threads that count to 1 million...
thread #6 won!
Note that as per the documentation, there are presently (CUDA 11.2) only implementations of:
<atomic>
<latch>
<barrier>
<semaphore>
<chrono>
<cfloat>
<ratio>
<climits>
<cstdint>
<type_traits>
<tuple>
<functional>
<utility>
<version>
<cassert>
<cstddef>
with complex support coming in the next CUDA release from the looks of things.
You mentioned shared pointers. There is no <memory> implementation at present, so that cannot be made to work.

file systems in C++

I'm working on a project in which I have to do some file handling.
If only someone could tell how to work with file system like
moving, copying, deleting, renaming and checking for the existence of files in Windows.
Check file management functions section on msdn.
For example, to copy a file with WinAPI you can use CopyFile:
#include <windows.h>
#include <iostream>
int main()
{
BOOL ret = CopyFile(TEXT("test.txt"), TEXT("test-copy.txt"), TRUE);
if (ret)
std::cout << "CopyFile failed. GetLastError:" << GetLastError() << std::endl;
}
If your compiler supports you may as well use std::filesystem which is portable (e.g. that code should work equally well on windows and linux):
#include <filesystem>
int main()
{
std::filesystem::copy("test.txt", "test-copy.txt");
}
There is also boost::filesystem that heavily influenced std::filesystem.

CodeBlocks with gmp, segfault with << operator and mp*_class

I am using CodeBlocks with gcc 4.7.2 and gmp 5.0.5 on a Win 7 64 machine.
After starting to use gmpxx I see a strange segfault which doesn't occur with the +,-,etc operators, but with << when trying to cout an mp*_class variable.
I have to say that gmpxx works perfectly so far except for this.
For example:
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main()
{
mpz_class c = 21;
cout << c << endl;
}
gives a segfault on the line with the cout, whereas the below code works fine:
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main()
{
mpz_class a = 3, b = 8, c;
c = a + b;
cout << c.get_str() << endl;
}
What is even stranger is that this code:
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main()
{
mpz_class a = 3, b = 8, c, d = 21;
c = a + b;
cout << c.get_str() << endl;
cout << d << endl;
}
doesn't segfault when run, but shows only the first result (11) and then exits normally.
On the other hand in debug it segfaults on: cout << d << endl.
I've googled for the last couple of days and found nothing similar to only some of the overloaded operators not working.
I would be thankful for an explanation.
I linked the two gmp libraries in codeblocks like this:
Settings->Compiler and Debugger->Global Compiler Settings->Linker Settings
and there I've added: C:\mingw\lib\libgmpxx.dll.a and C:\mingw\lib\libgmp.dll.a (in that order).
Nothing else was needed in order to compile c++ code with gmpxx.
Finally my CodeBlocks build log looks like this:
g++.exe -pg -g -pg -g -c "C:\Temp\test.cpp" -o .objs\test.o
g++.exe -o test.exe .objs\test.o -pg -lgmon -pg -lgmon C:\mingw\lib\libgmpxx.dll.a C:\mingw\lib\libgmp.dll.a
I honestly don't know why there are two switches of each.
If you need any more info, I'd be glad to provide. Thank you.
Alright, time to mark this as answered. The fact is that I installed gmp via mingw-get whereas almost everywhere in googleland it states to build it yourself for your own system. A silly mistake and thanks to the comment by #Lol4t0 it works fine now.
So for all the new guys like me:
1) Install MinGW with MSYS
2) Download gmp source and extract to some folder in mingw\msys\1.0\home\
3) open mingw shell and navigate to gmp folder
4) ./configure --enable-cxx --prefix=/home/newgmpinstall
5) make
6) make install
7) make check
If it checks ok then in newgmpinstall you'll find the headers gmp.h and gmpxx.h and libraries libgmp.a and libgmpxx.a which work for your system.
You can move them to a new folder if you wish. Then in your IDE Project properties add the *.a files to your link libraries and the folder with the *.h files to the compiler search directories.
Write code
Note: At first ./configure exited with an error about M4 missing because I was missing the M4 package. Just download the source for M4 and do the above steps first for M4 and then install gmp.

How to create a temporary directory in C++?

I'm writing a function in C++ which creates a temporary directory. Such function should be as most portable as possible, e.g. it should work under linux, mac and win32 environments. How do I achieve that?
Version 3 of Boost Filesystem Library provides function unique_path() for generating a path name suitable for creating a temporary file or directory.
using namespace boost::filesystem;
path ph = temp_directory_path() / unique_path();
create_directories(ph);
C++17 std::filesystem::temp_directory_path + random number generation
Here is a pure C++17 solution that might be reliable: no Boost or other external libraries and no mkdtemp which is POSIX.
We just loop over random numbers until we are able to create a directory that did not exist before inside std::filesystem::temp_directory_path (/tmp in Ubuntu 18.04).
We can then explicitly remove the created directory with std::filesystem::remove_all after we are done with it.
I'm not sure that the C++ standard guarantees this, but is extremely likely that std::filesystem::temp_directory_path calls mkdir, which atomically tries to create the directory and if it can't fails with EEXIST, so I don't think there can be race conditions across parallel callers.
main.cpp
#include <exception>
#include <fstream>
#include <iostream>
#include <random>
#include <sstream>
#include <filesystem>
std::filesystem::path create_temporary_directory(
unsigned long long max_tries = 1000) {
auto tmp_dir = std::filesystem::temp_directory_path();
unsigned long long i = 0;
std::random_device dev;
std::mt19937 prng(dev());
std::uniform_int_distribution<uint64_t> rand(0);
std::filesystem::path path;
while (true) {
std::stringstream ss;
ss << std::hex << rand(prng);
path = tmp_dir / ss.str();
// true if the directory was created.
if (std::filesystem::create_directory(path)) {
break;
}
if (i == max_tries) {
throw std::runtime_error("could not find non-existing directory");
}
i++;
}
return path;
}
int main() {
auto tmpdir = create_temporary_directory();
std::cout << "create_temporary_directory() = "
<< tmpdir
<< std::endl;
// Use our temporary directory: create a file
// in it and write to it.
std::ofstream ofs(tmpdir / "myfile");
ofs << "asdf\nqwer\n";
ofs.close();
// Remove the directory and its contents.
std::filesystem::remove_all(tmpdir);
}
GitHub upstream.
Compile and run:
g++-8 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp -lstdc++fs
./main.out
Sample output:
_directory.out
temp_directory_path() = "/tmp"
create_temporary_directory() = "/tmp/106adc08ff89874c"
For files, see: How to create a temporary text file in C++? Files are a bit different because open in Linux has the O_TMPFILE, which creates an anonymous inode that automatically disappears on close, so dedicated temporary file APIs can be more efficient by using that. There is no analogous flag for mkdir however, so this solution might be optimal.
Tested in Ubuntu 18.04.
Check the mkdtemp function here.
Boost's Filesystem library provides platform-independent directory functions. It will increase your program size a bit, but using Boost is often better (and often easier) than rolling your own.
http://www.boost.org/doc/libs/1_43_0/libs/filesystem/doc/index.htm
There's no standard function to do this, so you'll need to compile different implementations for each platform you target.
On Windows, for example, you should use the temp directory, which can be obtained by a call to GetTempPath().
mkdtemp(char *template)
http://www.cl.cam.ac.uk/cgi-bin/manpage?3+mkdtemp
Creates a temporary directory.