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

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.

Related

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

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;
}

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.

C++ --- Shouldn't these mathematical functions/constants be undefined?

I would not expect the following code that prints the value of sin(pi/2) to work, without the inclusion of an additional header:
#include <iostream>
int main()
{
std::cout << sin(0.5*M_PI) << std::endl;
return 0;
}
and, as expected, upon compilation I get an error reading ‘sin’ was not declared in this scope and a similar error for the use of M_PI.
However, I am confused by the fact that if I include seemingly any boost library header, take just for example the lexical_cast.hpp, and instead run
#include <iostream>
#include <boost/lexical_cast.hpp>
int main()
{
std::cout << sin(0.5*M_PI) << std::endl;
return 0;
}
then the code works and it prints 1.
Why should including this boost header, which contains no definition of M_PI or sin(), allow this constant and function to be defined? Shouldn't I need to include a header, like math.h that includes these things for this to work?
Yes, it should work that way.
The boost headers you tried all have implicit dependencies (pow(), modf(), fmod(), log() etc).
This is a common thing in the C++ compilation model. Nothing to be alarmed by.
Guideline: always explicitly include the headers you directly depend on. And only those.
This prevents portability issues on platforms where the library header dependency tree differs e.g. <algorithms> and <numeric> aren't implicitly included with some other standard library headers (e.g. MSVC)

std::greater not defined in MSVC2012

How come that std::greater is no more part of the std namespace in Visual Studio 2012? I now need to include <functional>
I thought STL libraries remained the same across toolsets
How come that std::greater is no more part of the std namespace in Visual Studio 2012?
I'd be very surprised if that were the case.
I now need to include <functional.h>
No, you need to include <functional> since that's the header that defines all the standard function objects, including greater.
I thought STL libraries remained the same across toolsets
They should be. But headers are allowed to include other headers, so sometimes you'll find that something is available even if you haven't included the correct header. But you can't rely on that, as you've found here. Always include all the headers you need for the things you use.
The following example, taken from here, compiles and executes correctly for me in Visual Studio 2012:
// greater example
#include <iostream> // std::cout
#include <functional> // std::greater
#include <algorithm> // std::sort
int main () {
int numbers[]={20,40,50,10,30};
std::sort (numbers, numbers+5, std::greater<int>());
for (int i=0; i<5; i++)
std::cout << numbers[i] << ' ';
std::cout << '\n';
return 0;
}
Output:
50 40 30 20 10
As per the question comments and the example above, you need to include <functional>, not <functional.h>.

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.