How to implement this script about concurrency in c++ 11 - c++11

I implement an concurrency script of multi thread in c++ 11 . But i stuck .
int product_val = 0;
- thread 1 : increase product_val to vector in thread 2 , notify thread 2 and waiting for thread 2 print product_val;
- thread 2 : wait and decrease product_val , print product_val
1 #include <iostream>
2 #include <thread>
3 #include <condition_variable>
4 #include <mutex>
5 #include <chrono>
6 #include <queue>
7 using namespace std;
8 int product_val = 0;
9 std::condition_variable cond;
10 std::mutex sync;
11 int main() {
12 //thread 2
13 std::thread con = std::thread([&](){
14 while (1)
15 {
16 std::unique_lock<std::mutex> l(sync);
17 cond.wait(l);
18 product_val--;
19 printf("Consumer product_val = %d \n", product_val);
20 l.unlock();
21 }
22 });
23 //thread 1 (main thread) process
24 for (int i = 0; i < 5; i++)
25 {
26 std::unique_lock<std::mutex> l(sync);
27 product_val++;
28 std::cout << "producer product val " << product_val;
29 cond.notify_one();
30 l.unlock();
31 l.lock();
32 while (product_val)
33 {
34
35 }
36 std::cout << "producer product val " << product_val;
37 l.unlock();
38 }
39 return 0;
40 }

Related

Producer consumer using boost::interprocess_confition with boost:interprocess shared memory. Consumer dominates 100%

Just making a simple example because I am having issues with a more complex usecase and want to udnerstand the base case before spending too much time in trial and error.
Scenario:
I have two binaries that supposedly takes turns incrementing a number (stored in shared memory). What happens in practice is that the "consumer" app takes over 100% never letting the "creator" run.
If I add a small delay in the consumer in that case I obtain the intended behaviour.
Simple POD struct
#pragma once
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
namespace bip = boost::interprocess;
namespace my_namespace {
static const char *name = "MySharedMemory";
struct MyStruct {
bip::interprocess_mutex mutex;
bip::interprocess_condition cond;
unsigned long counter;
MyStruct(): mutex(), cond(), counter(0) {
}
};
} // namespace my_namespace
"Creator/producer"
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/thread/locks.hpp>
#include "my_struct.h"
bool exit_flag = false;
void my_handler(int) {
exit_flag = true;
}
namespace bip = boost::interprocess;
int main() {
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = my_handler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
bip::shared_memory_object::remove(my_namespace::name);
auto memory = bip::managed_shared_memory(bip::create_only, my_namespace::name, 65536);
auto *data = memory.construct<my_namespace::MyStruct>(my_namespace::name)();
long unsigned iterations = 0;
while (!exit_flag) {
boost::interprocess::scoped_lock lock(data->mutex);
data->counter++;
std::cout << "iteration:" << iterations << "Counter: " << data->counter << std::endl;
++iterations;
auto start = boost::posix_time::microsec_clock::universal_time();
auto wait_time = start + boost::posix_time::milliseconds(1000);
auto ret = data->cond.timed_wait(lock, wait_time);
if (!ret) {
std::cout << "Timeout" << std::endl;
}
}
return 0;
}
Consumer
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sched.h>
#include <chrono>
#include <iostream>
#include <thread>
#include <mutex>
#include "my_struct.h"
bool exit_flag = false;
void my_handler(int) {
exit_flag = true;
}
namespace bip = boost::interprocess;
int fib(int x) {
if ((x == 1) || (x == 0)) {
return (x);
} else {
return (fib(x - 1) + fib(x - 2));
}
}
int main() {
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = my_handler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, nullptr);
auto memory = bip::managed_shared_memory(bip::open_only, my_namespace::name);
auto *data = memory.find<my_namespace::MyStruct>(my_namespace::name).first;
long unsigned iterations = 0;
while (!exit_flag) {
{
boost::interprocess::scoped_lock lock(data->mutex);
std::this_thread::sleep_for(std::chrono::milliseconds(200));
data->counter += 1;
std::cout << "iteration:" << iterations << "Counter: " << data->counter << std::endl;
++iterations;
std::cout << "notify_one" << std::endl;
data->cond.notify_one();
}
// usleep(1); // If I add this it works
}
return 0;
}
If someone can shed some light I would be grateful.
You're doing sleeps while holding the lock. This maximizes lock contention. E.g. in your consumer
boost::interprocess::scoped_lock lock(data->mutex);
std::this_thread::sleep_for(200ms);
Could be
std::this_thread::sleep_for(200ms);
boost::interprocess::scoped_lock lock(data->mutex);
Mutexes are supposed to synchronize access to shared resources. As long as you do not require exclusive access to the shared resource, don't hold the lock. In general, make access atomic and as short as possible in any locking scenario.
Side Notes
You don't need the complicated posix_time manipulation:
auto ret = data->cond.wait_for(lock, 1000ms);
if (bip::cv_status::timeout == ret) {
std::cout << "Timeout" << std::endl;
}
Just for sharing a single POD struct, managed_shared_memory is a lot of overkill. Consider mapped_region.
Consider Asio for signal handling. In any case, make the exit_flag atomic so you don't suffer a data race:
static std::atomic_bool exit_flag{false};
{
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = [](int) { exit_flag = true; };
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
}
Since your application is symmetrical, I'd expect the signaling to be symmetrical. If not, I'd expect the producing side to do signaling (after all, presumably there is nothing to consume when nothing was produced. Why be "busy" when you know nothing was produced?).
Live Demo
Live On Coliru
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <iostream>
#include <mutex>
#include <thread>
#include <signal.h>
#include <unistd.h>
#ifdef COLIRU // coliru doesn't support shared memory
#include <boost/interprocess/managed_mapped_file.hpp>
#define managed_shared_memory managed_mapped_file
#endif
namespace bip = boost::interprocess;
using namespace std::chrono_literals;
namespace my_namespace {
static char const* name = "MySharedMemory";
struct MyStruct {
bip::interprocess_mutex mutex;
bip::interprocess_condition cond;
unsigned long counter = 0;
};
} // namespace my_namespace
namespace producer {
void run() {
static std::atomic_bool exit_flag{false};
{
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = [](int) { exit_flag = true; };
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
}
bip::shared_memory_object::remove(my_namespace::name);
auto memory = bip::managed_shared_memory(bip::create_only, my_namespace::name, 65536);
auto& data = *memory.construct<my_namespace::MyStruct>(my_namespace::name)();
for (size_t iterations = 0; !exit_flag;) {
std::unique_lock lock(data.mutex);
data.counter++;
std::cout << "iteration:" << iterations << " Counter: " << data.counter << std::endl;
++iterations;
auto ret = data.cond.wait_for(lock, 1000ms);
if (bip::cv_status::timeout == ret) {
std::cout << "Timeout" << std::endl;
}
}
}
}
namespace consumer {
namespace bip = boost::interprocess;
void run() {
static std::atomic_bool exit_flag{false};
{
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = [](int) { exit_flag = true; };
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, nullptr);
}
bip::managed_shared_memory memory(bip::open_only, my_namespace::name);
auto& data = *memory.find<my_namespace::MyStruct>(my_namespace::name).first;
for (size_t iterations = 0; !exit_flag;) {
std::this_thread::sleep_for(200ms);
std::unique_lock lock(data.mutex);
data.counter += 1;
std::cout << "iteration:" << iterations << " Counter: " << data.counter << std::endl;
++iterations;
std::cout << "notify_one" << std::endl;
data.cond.notify_one();
}
}
}
int main(int argc, char**) {
if (argc>1)
producer::run();
else
consumer::run();
}
Testing with
g++ -std=c++20 -O2 -pthread main.cpp -lrt -DCOLIRU
./a.out producer&
sleep 1;
./a.out&
sleep 4; kill -INT %2; sleep 3;
./a.out&
sleep 4; kill -INT %1 %2 %3
Prints e.g.
PRODUCER iteration:0 Counter: 1
PRODUCER Timeout
PRODUCER iteration:1 Counter: 2
CONSUMER iteration:0 Counter: 3
CONSUMER notify_one
PRODUCER iteration:2 Counter: 4
CONSUMER iteration:1 Counter: 5
CONSUMER notify_one
PRODUCER iteration:3 Counter: 6
CONSUMER iteration:2 Counter: 7
CONSUMER notify_one
PRODUCER iteration:4 Counter: 8
CONSUMER iteration:3 Counter: 9
CONSUMER notify_one
PRODUCER iteration:5 Counter: 10
CONSUMER iteration:4 Counter: 11
CONSUMER notify_one
PRODUCER iteration:6 Counter: 12
CONSUMER iteration:5 Counter: 13
CONSUMER notify_one
PRODUCER iteration:7 Counter: 14
CONSUMER iteration:6 Counter: 15
CONSUMER notify_one
PRODUCER iteration:8 Counter: 16
CONSUMER iteration:7 Counter: 17
CONSUMER notify_one
PRODUCER iteration:9 Counter: 18
CONSUMER iteration:8 Counter: 19
CONSUMER notify_one
PRODUCER iteration:10 Counter: 20
CONSUMER iteration:9 Counter: 21
CONSUMER notify_one
PRODUCER iteration:11 Counter: 22
CONSUMER iteration:10 Counter: 23
CONSUMER notify_one
PRODUCER iteration:12 Counter: 24
CONSUMER iteration:11 Counter: 25
CONSUMER notify_one
PRODUCER iteration:13 Counter: 26
CONSUMER iteration:12 Counter: 27
CONSUMER notify_one
PRODUCER iteration:14 Counter: 28
CONSUMER iteration:13 Counter: 29
CONSUMER notify_one
PRODUCER iteration:15 Counter: 30
CONSUMER iteration:14 Counter: 31
CONSUMER notify_one
PRODUCER iteration:16 Counter: 32
CONSUMER iteration:15 Counter: 33
CONSUMER notify_one
PRODUCER iteration:17 Counter: 34
CONSUMER iteration:16 Counter: 35
CONSUMER notify_one
PRODUCER iteration:18 Counter: 36
CONSUMER iteration:17 Counter: 37
CONSUMER notify_one
PRODUCER iteration:19 Counter: 38
CONSUMER iteration:18 Counter: 39
CONSUMER notify_one
PRODUCER iteration:20 Counter: 40
CONSUMER iteration:19 Counter: 41
CONSUMER notify_one
PRODUCER iteration:21 Counter: 42
PRODUCER Timeout
PRODUCER iteration:22 Counter: 43
PRODUCER Timeout
PRODUCER iteration:23 Counter: 44
PRODUCER Timeout
PRODUCER iteration:24 Counter: 45
CONSUMER iteration:0 Counter: 46
CONSUMER notify_one
PRODUCER iteration:25 Counter: 47
CONSUMER iteration:1 Counter: 48
CONSUMER notify_one
PRODUCER iteration:26 Counter: 49
CONSUMER iteration:2 Counter: 50
CONSUMER notify_one
PRODUCER iteration:27 Counter: 51
CONSUMER iteration:3 Counter: 52
CONSUMER notify_one
PRODUCER iteration:28 Counter: 53
CONSUMER iteration:4 Counter: 54
CONSUMER notify_one
PRODUCER iteration:29 Counter: 55
CONSUMER iteration:5 Counter: 56
CONSUMER notify_one
PRODUCER iteration:30 Counter: 57
CONSUMER iteration:6 Counter: 58
CONSUMER notify_one
PRODUCER iteration:31 Counter: 59
CONSUMER iteration:7 Counter: 60
CONSUMER notify_one
PRODUCER iteration:32 Counter: 61
CONSUMER iteration:8 Counter: 62
CONSUMER notify_one
PRODUCER iteration:33 Counter: 63
CONSUMER iteration:9 Counter: 64
CONSUMER notify_one
PRODUCER iteration:34 Counter: 65
CONSUMER iteration:10 Counter: 66
CONSUMER notify_one
PRODUCER iteration:35 Counter: 67
CONSUMER iteration:11 Counter: 68
CONSUMER notify_one
PRODUCER iteration:36 Counter: 69

Unable to compile thrust code using reduce_by_key

I need to minimum values along columns of a matrix along with row indices using thrust. I use the following code (copied from orange owl solutions), However I get errors while compiling. I have posted it as an issue on the corresponding git page. The error message is huge and i dont know how to debug it. Can anyone help me with it? I am using cuda-8.0, thrust version 1.8.
The code:
#include <iterator>
#include <algorithm>
#include <thrust/device_vector.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/iterator/permutation_iterator.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/iterator/discard_iterator.h>
#include <thrust/reduce.h>
#include <thrust/functional.h>
#include <thrust/random.h>
using namespace thrust::placeholders;
int main()
{
const int Nrows = 6;
const int Ncols = 8;
/**************************/
/* SETTING UP THE PROBLEM */
/**************************/
// --- Random uniform integer distribution between 0 and 100
thrust::default_random_engine rng;
thrust::uniform_int_distribution<int> dist(0, 20);
// --- Matrix allocation and initialization
thrust::device_vector<double> d_matrix(Nrows * Ncols);
for (size_t i = 0; i < d_matrix.size(); i++) d_matrix[i] = (double)dist(rng);
printf("\n\nMatrix\n");
for(int i = 0; i < Nrows; i++) {
std::cout << " [ ";
for(int j = 0; j < Ncols; j++)
std::cout << d_matrix[i * Ncols + j] << " ";
std::cout << "]\n";
}
/**********************************************/
/* FIND ROW MINIMA ALONG WITH THEIR LOCATIONS */
/**********************************************/
thrust::device_vector<float> d_minima(Ncols);
thrust::device_vector<int> d_indices(Ncols);
thrust::reduce_by_key(
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), _1 / Nrows),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), _1 / Nrows) + Nrows * Ncols,
thrust::make_zip_iterator(
thrust::make_tuple(thrust::make_permutation_iterator(
d_matrix.begin(),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 % Nrows) * Ncols + _1 / Nrows)),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), _1 % Nrows))),
thrust::make_discard_iterator(),
thrust::make_zip_iterator(thrust::make_tuple(d_minima.begin(), d_indices.begin())),
thrust::equal_to<int>(),
thrust::minimum<thrust::tuple<float, int> >()
);
printf("\n\n");
for (int i=0; i<Nrows; i++) std::cout << "Min position = " << d_indices[i] << "; Min value = " << d_minima[i] << "\n";
return 0;
}
Error :
/usr/local/cuda/bin/../targets/x86_64-linux/include/thrust/system/cuda/detail/bulk/algorithm/reduce_by_key.hpp(58): error: ambiguous "?" operation: second operand of type "const thrust::tuple<double, int, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type>" can be converted to third operand type "thrust::tuple<float, int, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type>", and vice versa
detected during:
instantiation of "thrust::system::cuda::detail::bulk_::detail::reduce_by_key_detail::scan_head_flags_functor<FlagType, ValueType, BinaryFunction>::result_type thrust::system::cuda::detail::bulk_::detail::reduce_by_key_detail::scan_head_flags_functor<FlagType, ValueType, BinaryFunction>::operator()(const thrust::system::cuda::detail::bulk_::detail::reduce_by_key_detail::scan_head_flags_functor<FlagType, ValueType, BinaryFunction>::first_argument_type &, const thrust::system::cuda::detail::bulk_::detail::reduce_by_key_detail::scan_head_flags_functor<FlagType, ValueType, BinaryFunction>::second_argument_type &) [with FlagType=int, ValueType=thrust::tuple<double, int, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type>, BinaryFunction=thrust::minimum<thrust::tuple<float, int, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type>>]"
I guess you are using this code.
A curious characteristic of that code is that the matrix is defined using double type, but the captured minima are stored in a float vector.
If you want to use that code as-is, according to my testing, thrust (in CUDA 10, and apparently also CUDA 8) doesn't like this line:
thrust::minimum<thrust::tuple<float, int> >()
That operator is being used to compare two items to determine which is smaller, and it is templated to accept different kinds of items. However, it has decided that finding the minimum of two of those tuples is an "ambiguous" request. Part of the reason for this is that the operator returns a float, int tuple, but is being given variously a double,int tuple or a float,int tuple.
We can fix/work around this by passing our own functor to do the job, that is explicit in terms of handling the tuples passed to it:
$ cat t373.cu
#include <iterator>
#include <algorithm>
#include <thrust/device_vector.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/iterator/permutation_iterator.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/iterator/discard_iterator.h>
#include <thrust/reduce.h>
#include <thrust/functional.h>
#include <thrust/random.h>
using namespace thrust::placeholders;
struct my_min
{
template <typename T1, typename T2>
__host__ __device__
T2 operator()(T1 t1, T2 t2){
if (thrust::get<0>(t1) < thrust::get<0>(t2)) return t1;
return t2;
}
};
int main()
{
const int Nrows = 6;
const int Ncols = 8;
/**************************/
/* SETTING UP THE PROBLEM */
/**************************/
// --- Random uniform integer distribution between 0 and 100
thrust::default_random_engine rng;
thrust::uniform_int_distribution<int> dist(0, 20);
// --- Matrix allocation and initialization
thrust::device_vector<double> d_matrix(Nrows * Ncols);
for (size_t i = 0; i < d_matrix.size(); i++) d_matrix[i] = (double)dist(rng);
printf("\n\nMatrix\n");
for(int i = 0; i < Nrows; i++) {
std::cout << " [ ";
for(int j = 0; j < Ncols; j++)
std::cout << d_matrix[i * Ncols + j] << " ";
std::cout << "]\n";
}
/**********************************************/
/* FIND ROW MINIMA ALONG WITH THEIR LOCATIONS */
/**********************************************/
thrust::device_vector<float> d_minima(Ncols);
thrust::device_vector<int> d_indices(Ncols);
thrust::reduce_by_key(
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 / Nrows)),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 / Nrows)) + Nrows * Ncols,
thrust::make_zip_iterator(
thrust::make_tuple(thrust::make_permutation_iterator(
d_matrix.begin(),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), ((_1 % Nrows) * Ncols + _1 / Nrows))),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 % Nrows)))),
thrust::make_discard_iterator(),
thrust::make_zip_iterator(thrust::make_tuple(d_minima.begin(), d_indices.begin())),
thrust::equal_to<int>(),
my_min()
// thrust::minimum<thrust::tuple<float, int> >()
);
printf("\n\n");
for (int i=0; i<Nrows; i++) std::cout << "Min position = " << d_indices[i] << "; Min value = " << d_minima[i] << "\n";
return 0;
}
$ nvcc -o t373 t373.cu
$ ./t373
Matrix
[ 0 1 12 18 20 3 10 8 ]
[ 5 15 1 11 12 17 12 10 ]
[ 18 20 15 20 6 8 18 13 ]
[ 18 20 3 18 19 6 19 8 ]
[ 6 10 8 16 14 11 12 1 ]
[ 12 9 12 17 10 16 1 4 ]
Min position = 0; Min value = 0
Min position = 0; Min value = 1
Min position = 1; Min value = 1
Min position = 1; Min value = 11
Min position = 2; Min value = 6
Min position = 0; Min value = 3
$
I think a better fix is to just choose one or the other, either float or double. If we modify all float types to double, for example, then thrust is happy, without any other changes:
$ cat t373a.cu
#include <iterator>
#include <algorithm>
#include <thrust/device_vector.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/iterator/permutation_iterator.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/iterator/discard_iterator.h>
#include <thrust/reduce.h>
#include <thrust/functional.h>
#include <thrust/random.h>
using namespace thrust::placeholders;
int main()
{
const int Nrows = 6;
const int Ncols = 8;
/**************************/
/* SETTING UP THE PROBLEM */
/**************************/
// --- Random uniform integer distribution between 0 and 100
thrust::default_random_engine rng;
thrust::uniform_int_distribution<int> dist(0, 20);
// --- Matrix allocation and initialization
thrust::device_vector<double> d_matrix(Nrows * Ncols);
for (size_t i = 0; i < d_matrix.size(); i++) d_matrix[i] = (double)dist(rng);
printf("\n\nMatrix\n");
for(int i = 0; i < Nrows; i++) {
std::cout << " [ ";
for(int j = 0; j < Ncols; j++)
std::cout << d_matrix[i * Ncols + j] << " ";
std::cout << "]\n";
}
/**********************************************/
/* FIND ROW MINIMA ALONG WITH THEIR LOCATIONS */
/**********************************************/
thrust::device_vector<double> d_minima(Ncols);
thrust::device_vector<int> d_indices(Ncols);
thrust::reduce_by_key(
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 / Nrows)),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 / Nrows)) + Nrows * Ncols,
thrust::make_zip_iterator(
thrust::make_tuple(thrust::make_permutation_iterator(
d_matrix.begin(),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), ((_1 % Nrows) * Ncols + _1 / Nrows))),
thrust::make_transform_iterator(thrust::make_counting_iterator((int) 0), (_1 % Nrows)))),
thrust::make_discard_iterator(),
thrust::make_zip_iterator(thrust::make_tuple(d_minima.begin(), d_indices.begin())),
thrust::equal_to<int>(),
thrust::minimum<thrust::tuple<double, int> >()
);
printf("\n\n");
for (int i=0; i<Nrows; i++) std::cout << "Min position = " << d_indices[i] << "; Min value = " << d_minima[i] << "\n";
return 0;
}
$ nvcc -o t373a t373a.cu
$ ./t373a
Matrix
[ 0 1 12 18 20 3 10 8 ]
[ 5 15 1 11 12 17 12 10 ]
[ 18 20 15 20 6 8 18 13 ]
[ 18 20 3 18 19 6 19 8 ]
[ 6 10 8 16 14 11 12 1 ]
[ 12 9 12 17 10 16 1 4 ]
Min position = 0; Min value = 0
Min position = 0; Min value = 1
Min position = 1; Min value = 1
Min position = 1; Min value = 11
Min position = 2; Min value = 6
Min position = 0; Min value = 3
$
I think this latter solution of using consistent types is the more sensible solution.

MinGW boost random_device compile error

I need some random numbers for a simulation and are experimenting with the C++ 11 random library using MinGW Distro from nuwen.net.
As have been discussed in several other threads, e.g. Why do I get the same sequence for every run with std::random_device with mingw gcc4.8.1?, random_device do not generate a random seed, i.e. the code below, compiled with GCC, generates the same sequence of numbers for every run.
// test4.cpp
// MinGW Distro - nuwen.net
// Compile with g++ -Wall -std=c++14 test4.cpp -o test4
#include <iostream>
#include <random>
using namespace std;
int main(){
random_device rd;
mt19937 mt(rd());
uniform_int_distribution<int> dist(0,99);
for (int i = 0; i< 16; ++i){
cout<<dist(mt)<<" ";
}
cout <<endl;
}
Run 1: 56 72 34 91 0 59 87 51 95 97 16 66 31 52 70 78
Run 2: 56 72 34 91 0 59 87 51 95 97 16 66 31 52 70 78
To solve this problem it has been suggested to use the boost library, and the code would then look something like below, adopted from How do I use boost::random_device to generate a cryptographically secure 64 bit integer? and from A way change the seed of boost::random in every different program run,
// test5.cpp
// MinGW Distro - nuwen.net
// Compile with g++ -Wall -std=c++14 test5.cpp -o test5
#include <boost/random.hpp>
#include <boost/random/random_device.hpp>
#include <iostream>
#include <random>
using namespace std;
int main(){
boost::random_device rd;
mt19937 mt(rd());
uniform_int_distribution<int> dist(0,99);
for (int i = 0; i< 16; ++i){
cout<<dist(mt)<<" ";
}
cout <<endl;
}
But this code wont compile, gives the error “undefined reference to ‘boost::random::random_device::random_device()”. Note that both random.hpp and radndom_device.hpp are available in the include directory. Can anyone suggest what is wrong with the code, or with the compiling?
Linking the code to the boost libraries libboost_random.a and libboost_system.a seems to solve the problem, the executable generates of list of different random numbers for each run.
// test5.cpp
// MinGW Distro - nuwen.net
// g++ -std=c++14 test5.cpp -o test5 E:\MinGW\lib\libboost_random.a E:\MinGW\lib\libboost_system.a
#include <boost/random.hpp>
#include <boost/random/random_device.hpp>
#include <iostream>
#include <random>
using namespace std;
int main(){
boost::random_device rd;
boost::mt19937 mt(rd());
uniform_int_distribution<int> dist(0,99);
for (int i = 0; i< 16; ++i){
cout<<dist(mt)<<" ";
}
cout <<endl;
}
Run 1: 20 89 31 30 74 3 93 43 68 4 64 38 74 37 4 69
Run 2: 40 85 99 72 99 29 95 32 98 73 95 88 37 59 79 66

Reading a file containing characters in parentheses into a vector of integers

I am attempting to read in a file containing characters enclosed in parentheses into a vector of integers.
My text file:
(2 3 4 9 10 14 15 16 17 19)
Heres my code:
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int main(){
ifstream file;
file.open("moves.txt");
vector<int> V;
char c;
if (file){
while (file.get(c)){
if (c != '(' && c != ')' && c != ' ')
V.push_back(c - '0');
}
}
else{
cout << "Error openning file." << endl;
}
for (int i = 0; i < V.size(); i++)
cout << V[i] << endl;
}
My Output:
2
3
4
9
1
0
1
4
1
5
1
6
1
7
1
9
-38
Desired output:
2
3
4
9
10
14
15
16
17
19
What is causing the separation of two digit numbers and why is there a negative number at the end of my output?
Don't read characters one by one : read a line, and parse the numbers within it.
By using the is_number (c++11) function of this answer :
bool is_number(const std::string& s)
{
return !s.empty() && std::find_if(s.begin(),
s.end(), [](char c) { return !std::isdigit(c); }) == s.end();
}
You can read line by line with std::getline and then stream the numbers to a std::stringstream. std::stoi can be used to convert a string to an integer :
std::string line;
while(std::getline(file, line))
{
line.replace(line.begin(), line.begin() + 1, "");
line.replace(line.end() - 2, line.end() - 1, "");
std::string numberStr;
std::stringstream ss(line);
while (ss >> numberStr){
if (is_number(numberStr))
v.push_back(std::stoi(numberStr));
}
}
You'd have to make the replace more robust (by checking the presence of parentheses at these positions)

macos: CCCrypt() decrypt output does not match original plaintext

In the code below, the decrypted text does not match the original plaintext. The first 12 bytes are messed up. Note that block cipher padding has been disabled. I have tried different values for BUF_SIZE, all multiples of 16 - every time the first 12 bytes of the decrypted data is wrong. Here's the output:
plain buf[32]:
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
outlen=32
outlen=32
dec buf[32]:
0C 08 01 46 6D 3D FC E9 98 0A 2D E1 AF A3 95 3A
0B 31 1B 9D 11 11 11 11 11 11 11 11 11 11 11 11
Here's the code:
#include <stdio.h>
#include <string.h>
#include <CommonCrypto/CommonCryptor.h>
static void
dumpbuf(const char* label, const unsigned char* pkt, unsigned int len)
{
const int bytesPerLine = 16;
if (label) {
printf("%s[%d]:\n", label, len);
}
for (int i = 0; i < int(len); i++) {
if (i && ((i % bytesPerLine) == 0)) {
printf("\n");
}
unsigned int c = (unsigned int)pkt[i] & 0xFFu;
printf("%02X ", c);
}
printf("\n");
}
int main(int argc, char* argv[])
{
unsigned char key[16];
unsigned char iv[16];
memset(key, 0x22, sizeof(key));
memset(iv, 0x33, sizeof(iv));
#define BUF_SIZE 32
unsigned char plainBuf[BUF_SIZE];
unsigned char encBuf[BUF_SIZE];
memset(plainBuf, 0x11, sizeof(plainBuf));
dumpbuf("plain buf", plainBuf, sizeof(plainBuf));
int outlen;
CCCryptorStatus status;
status = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, 0,
key, kCCKeySizeAES128, iv, plainBuf, sizeof(plainBuf),
encBuf, sizeof(encBuf), (size_t*)&outlen);
if (kCCSuccess != status) {
fprintf(stderr, "FEcipher: CCCrypt failure\n");
return -1;
}
printf("outlen=%d\n", outlen);
status = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, 0,
key, kCCKeySizeAES128, iv, encBuf, sizeof(encBuf),
plainBuf, sizeof(plainBuf), (size_t*)&outlen);
if (kCCSuccess != status) {
fprintf(stderr, "FEcipher: CCCrypt failure\n");
return -1;
}
printf("outlen=%d\n", outlen);
dumpbuf("dec buf", plainBuf, sizeof(plainBuf));
return 0;
}
Thanks,
Hari
#owlstead, thanks for your response. CBC is the default - you don't need to specify anything special in the options to enable it.
The same code using CCCrypt() was working before. I don't know what changed - may be a new library was installed during an update. Instead of using the convenience function CCCrypt() I'm now using the Create/Update/Final API - it works, so I have a workaround.
outlen should be size_t, not int.

Resources