This is my first try with the RcppParallel package and I have to work with C++17 (Ubuntu)
I tried to stay close to the ParallelFor example of the developers site, but I need an additional (non-iterative) argument for the worker threshold.
This is the my current code
struct ReplaceWorker : public Worker
{
// source matrix
const RMatrix<double> input;
// destination matrix
RMatrix<double> output;
// threshold
double th;
// initialize with source and destination
ReplaceWorker(const NumericMatrix input, NumericMatrix output, double threshold)
: input(input), output(output), th(threshold) {}
// replace function
template<typename T>
double replacer(const T &x){
if(x < th){
return(0);
} else {
return(1);
}
}
// take the square root of the range of elements requested
void operator()(std::size_t begin, std::size_t end) {
std::transform(input.begin() + begin,
input.begin() + end,
output.begin() + begin,
replacer);
}
};
However I always end up with the same compilation errors:
usr/include/c++/7/bits/stl_algo.h:4295:5: note: candidate: template<class _IIter, class _OIter, class _UnaryOperation> _OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation)
transform(_InputIterator __first, _InputIterator __last,
^~~~~~~~~
/usr/include/c++/7/bits/stl_algo.h:4295:5: note: template argument deduction/substitution failed:
network_edge_strength.cpp:173:28: note: couldn't deduce template parameter ‘_UnaryOperation’
replacer);
^
/usr/include/c++/7/bits/stl_algo.h:4332:5: note: candidate: template<class _IIter1, class _IIter2, class _OIter, class _BinaryOperation> _OIter std::transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation)
transform(_InputIterator1 __first1, _InputIterator1 __last1,
^~~~~~~~~
/usr/include/c++/7/bits/stl_algo.h:4332:5: note: template argument deduction/substitution failed:
network_edge_strength.cpp:173:28: note: candidate expects 5 arguments, 4 provided
replacer);
^
Any suggestions, how to fix this or alternatives, how to make it run with the required threshold parameter?
replacer is a function template, not a function, which means it cannot be used as a function object unless a specific instantiation is used, as otherwise template argument deduction fails.
Additionally, as a member function, it would require an implicit object parameter to be callable.
You could use a generic lambda expression instead:
std::transform(/* [...] */, [this] (const auto& x) { return replacer(x); });
This way, even if replacer is overloaded or is a function template, this will work.
Alternatively, remove replacer altogether, and use a lambda expression directly:
std::transform(/* [...] */, [this] (const auto& x) { return x < th ? 0 : 1; });
Related
In short:
There's a templatized class object "queue"
Another templatized object "task" contains a queue as first member (address of task will point to queue object)
An observer function receives only addresses to queues and calls queue's member function do_something(). However, one of those passed pointers is of type task*. This address will at the same time point to an object of type task and queue, however I want to keep this implementation detail hidden from the user.
Code:
#include <iostream>
template <int I>
struct queue
{
int i_ = I;
void do_something() {
std::cout << "do_something() called!" << std::endl;
}
};
queue<1> hello1;
queue<2> hello2;
template <int J>
struct task
{
queue<3> hello3;
int j_ = J;
};
task<1> task1;
template <typename... Ts>
void observe(Ts... Args)
{
(( static_cast<queue/* can't really specify template? */*>(Args)->do_something(), void()), ... );
}
int main()
{
observe(&hello1, &hello2, &task1);
}
I get this error:
<source>: In function 'void observe(Ts ...)':
<source>:29:20: error: missing template arguments after 'queue'
(( static_cast<queue/* can't really specify template? */*>(Args)->do_something(), void()), ... );
^~~~~
<source>:5:8: note: 'template<int I> struct queue' declared here
struct queue
^~~~~
<source>:29:96: error: operand of fold expression has no unexpanded parameter packs
(( static_cast<queue/* can't really specify template? */*>(Args)->do_something(), void()), ... );
^~~
Compiler returned: 1
Now my question is: Can I somehow cast the pointer to a pointer to queue<X>* so the calls to do_something() resolve correctly to a queue object? Or is there another way to achieve the same?
I wondered if there is an option to also hand over the current processed index with QtConcurrent::mapped(someVector, &someFunction)) (also filter, filtered, map,...)
What I want: I want to do something with the elements in someVector based on the current index in it. but since the function someFunction is only taking the type T which is also used for the QVector<T> vector.
What I did: Because I needed this, I created a QVector<std::pair<int, T>> and manually created the index for the elements.
Since this requires more space and is not a nice solution, I thought maybe there could be another solution.
Docs: https://doc.qt.io/qt-5/qtconcurrent-index.html
If your input is a QVector, you can make use of the fact that QVector stores all the elements contiguously. This means that given a reference to an element e in a QVector v, then the index of e can be obtained by:
std::ptrdiff_t idx = &e - &v.at(0);
Below is a complete example using QtConcurrent::mapped:
#include <iterator>
#include <numeric>
#include <type_traits>
#include <utility>
#include <QtCore>
#include <QtConcurrent>
// lambda functions are not directly usable in QtConcurrent::mapped, the
// following is a necessary workaround
// see https://stackoverflow.com/a/49821973
template <class T> struct function_traits :
function_traits<decltype(&T::operator())> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
// specialization for pointers to member function
using functor_type = ClassType;
using result_type = ReturnType;
using arg_tuple = std::tuple<Args...>;
static constexpr auto arity = sizeof...(Args);
};
template <class Callable, class... Args>
struct CallableWrapper : Callable, function_traits<Callable> {
CallableWrapper(const Callable &f) : Callable(f) {}
CallableWrapper(Callable &&f) : Callable(std::move(f)) {}
};
template <class F, std::size_t ... Is, class T>
auto wrap_impl(F &&f, std::index_sequence<Is...>, T) {
return CallableWrapper<F, typename T::result_type,
std::tuple_element_t<Is, typename T::arg_tuple>...>(std::forward<F>(f));
}
template <class F> auto wrap(F &&f) {
using traits = function_traits<F>;
return wrap_impl(std::forward<F>(f),
std::make_index_sequence<traits::arity>{}, traits{});
}
int main(int argc, char* argv[]) {
QCoreApplication app(argc, argv);
// a vector of numbers from 0 to 500
QVector<int> seq(500, 0);
std::iota(seq.begin(), seq.end(), 0);
qDebug() << "input: " << seq;
QFuture<int> mapped = QtConcurrent::mapped(seq, wrap([&seq](const int& x) {
// the index of the element in a QVector is the difference between
// the address of the first element in the vector and the address of
// the current element
std::ptrdiff_t idx = std::distance(&seq.at(0), &x);
// we can then use x and idx however we want
return x * idx;
}));
qDebug() << "output: " << mapped.results();
QTimer::singleShot(100, &app, &QCoreApplication::quit);
return app.exec();
}
See this question for a related discussion. Note that the linked question has a cleaner answer that involves the usage of zip and counting iterators from boost (or possibly their C++20 ranges counterparts), but I don't think that this would play well with QtConcurrent::map when map slices the sequence into blocks, and distributes these blocks to multiple threads.
I am shifting from Python to C so bit rusty on the semantics as well as coding habit. In Python everything is treated as an object and objects are passed to functions. This is not the case in C so I want to increment an integer using pointers. What is the correct assignment to do so. I want to do it the following way but have the assignments wrong:
#include <stdio.h>
int i = 24;
int increment(*i){
*i++;
return i;
}
int main() {
increment(&i);
printf("i = %d, i);
return 0;
}
I fixed your program:
#include <stdio.h>
int i = 24;
// changed from i to j in order to avoid confusion.
// note you could declare the return type as void instead
int increment(int *j){
(*j)++;
return *j;
}
int main() {
increment(&i);
printf("i = %d", i);
return 0;
}
Your main error was the missing int in the function's argument (also a missing " in the printf).
Also I would prefer using parentheses in expressions as *j++ and specify exactly the precedence like I did in (*j)++, because I want to increment the content of the variable in the 'j' location not to increment the pointer - meaning to point it on the next memory cell - and then use its content.
I recent begin to read cat.c and was confused with the function io_blksize, this function defined as follow:
static inline size_t
io_blksize (struct stat sb)
{
return MAX (IO_BUFSIZE, ST_BLKSIZE (sb));
}
and
enum { IO_BUFSIZE = 128*1024 };
#define DEV_BSIZE 4096
#define ST_BLKSIZE (statbuf) DEV_BSIZE
Now, the problem is io_blksize seemed always return IO_BUFSIZE, why not just defined the function:
static inline size_t
io_blksize (struct stat sb)
{
return IO_BUFSIZE;
}
and in the macro ST_BLKSIZE what's the effect of parameters sb?ST_BLKSIZE(sb) seem to return 4096 always.
io_blksize() returns at least 128KiB, but it may be larger in some situations on NFS for example. The reasoning behind the 128KiB value is detailed in src/ioblksize.h.
I want to use something like
typedef double Matrix[4][4];
to represent transformations and also pass them around with the QT signal/slot mechanism. But when I use
Q_DECLARE_METATYPE(Matrix)
it throws an error in qmetatype.h at this function
void *qMetaTypeConstructHelper(const T *t)
{
if (!t)
return new T();
return new T(*static_cast<const T*>(t));
}
saying: "error C2075: 'Target of operator new()' : array initialization needs curly braces"
Q_DECLARE_METATYPE(T) requires the type T to be default-constructable, copiable and destructable. Your Matrix type is not copiable, thus you can't use Q_DECLARE_METATYPE on it.
Workaround: use a class.
// copiable, C++98 brace-initializable, etc.
struct Matrix {
double data[4][4];
};
Ideally you should be using eigen3 and its types. Alternatively, wrap your type in a class. Once you do it, you might as well have the class do more than be a mere wrapper. Eventually, you'll see that eigen3 is the only sane way to proceed. Probably when you get to this point:
#include <cstring>
class Matrix {
double m_data[4][4];
public:
typedef double (*Data)[4];
Matrix() {}
Matrix(const Matrix & other) { memcpy(m_data, other.m_data, sizeof m_data); }
Matrix & operator=(const Matrix & other) { memcpy(m_data, other.m_data, sizeof m_data); return *this; }
Matrix & operator=(const Data other) { memcpy(m_data, other, sizeof m_data); return *this; }
operator Data() { return m_data; }
};
int main()
{
double mat1[4][4];
Matrix mat2;
mat2[3][3] = 1;
mat2 = mat1;
return 0;
}