My goal is to speed up my code by removing the runtime decision making of if-statements. Here's a simple example:
enum E
{
E_A,
E_B
};
class Example:
{
public:
void DoSomething(E var)
{
if (var == E_A) {
// Do stuff with a
} else if (var == E_B) {
// Do stuff with b
}
}
private:
set<int> a;
set<int> b;
}
I've split the above DoSomething() function into 2.
void DoSomething(E::E_A var) {
// Do stuff with a
}
void DoSomething(E::E_B var) {
// Do stuff with b
}
The problem is I have to rewrite the same code twice... We could use an inbetween function:
void DoSomething(E_A var) {
InBetween(a);
}
void DoSomething(E_B var) {
InBetween(b);
}
void InBetween(set<int> s)
{
// Do something with s
}
set<int> a;
set<int> b;
However I was wondering if there's a way to achieve what I want with just a single DoSomething()? I want the code to have minimal runtime so please avoid solutions like storing storing a and b inside a map and looking up based on key.
Or please suggest me some areas to look into. Thanks in advance!
You can make DoSomething template (and var template parameter). Then you can apply Constexpr If (since C++17), which performs dispatch at compile-time. E.g.
template <E var>
void DoSomething()
{
if constexpr (var == E_A) {
// Do stuff with a
} else if constexpr (var == E_B) {
// Do stuff with b
}
}
Then call it as
a_Example.DoSomething<E::E_A>();
a_Example.DoSomething<E::E_B>();
Related
I would like to create something similar to rust unsafe scope in C++.
The idea is that I have some functions performing number of checks. For example:
void check() {
if (...)
throw exception(...);
}
void foo() {
check();
// do some work
}
Now, I want to be able to call function foo() with or (in different context) without performing those checks. Ideally it would look like this:
foo(); // call foo and perform checks
unsafe {
foo(); // call foo without checks
}
My question is, is it possible to achieve something like this in compile time? Is it possible to somehow check (or act differently) from check function in what scope it is called?
I came up only with a runtime solution: to wrap it in some lambda:
unsafe([&] {
foo();
});
where unsafe is implemented as follows:
void unsafe(std::function<void()> f)
{
thread_local_flag = unsafe;
f();
thread_local_flag = safe;
}
check() function would just check for the thread_local flag and perform checks only when it is set to safe.
🤔
namespace detail_unsafe {
thread_local int current_depth;
struct unsafe_guard {
unsafe_guard() { ++current_depth; }
~unsafe_guard() { --current_depth; }
unsafe_guard(unsafe_guard const &) = delete;
unsafe_guard &operator = (unsafe_guard const &) = delete;
};
}
#define unsafe \
if(::detail_unsafe::unsafe_guard _ug; false) {} else
bool currently_unsafe() {
return detail_unsafe::current_depth > 0;
}
See it live on Coliru. Also, please don't actually define unsafe as a macro...
is it possible to achieve something like this in compile time?
Not the way you presented. Making foo a template function might give you equivalent results, though:
enum class CallType // find a better name yourself...
{
SAFE,
UNSAFE,
};
template <CallType Type = CallType::SAFE>
void foo()
{
if constexpr(Type != CallType::UNSAFE)
{
if (...)
throw ...;
}
// do some work
}
You might call it like:
foo();
foo<CallType::UNSAFE>();
Disliking templates?
Simple approach (thanks, #VTT):
void check(); // no template any more
void foo_unsafe()
{
// do some work
}
inline void foo()
{
check();
foo_unsafe();
}
Or selecting via parameter (this pattern exists in standard library, too):
struct Unsafe
{
};
inline Unsafe unsafe;
void check();
void foo(Unsafe)
{
// do some work
}
inline void foo()
{
check();
foo(unsafe);
}
Edit:
Well, in the example I presented I could do that, but in general, I can call some other function bar inside unsafe which in turn calls foo. And I don't want to specialize bar and possible other methods.
Unter this constraint, the template variant might be the closest you can get to at compile time; you don't have to specialise all the functions, but you'd need to make templates from:
template <CallType Type = CallType::SAFE>
void bar()
{
// do some other work
foo<Type>(); // just call with template parameter
// yet some further work
}
I would simply use a RAII type to toggle the unsafe flag inside a scope as such:
thread_local bool unsafe_flag = false;
/// RAII Type that toggles the flag on while it's alive
/// Possibly add a reference counter so it can be used nested
struct unsafe_scope
{
constexpr unsafe_scope() { unsafe_flag = true; }
~unsafe_scope() { unsafe_flag = false; }
};
/// Gets a value from a pointer
int get_value(int* ptr)
{
if ( unsafe_flag )
{
if ( ptr == nullptr ) { return 0; }
}
return *ptr;
}
int main()
{
int* x = nullptr;
//return get_value(x); // Doesn't perform the check
{
unsafe_scope cur_scope;
return get_value(x); // Performs the check
}
}
In order to make it nested I would add a reference counter like this:
/// RAII Type that toggles the flag on while it's alive
struct unsafe_scope
{
thread_local static size_t ref_count;
constexpr unsafe_scope()
{
unsafe_flag = true;
ref_count++;
}
~unsafe_scope()
{
ref_count--;
if ( ref_count == 0 ) { unsafe_flag = false; }
}
};
/// In source file
thread_local size_t unsafe_scope::ref_count = 0;
The ref_count doesn't need to be atomic since it's thread_local
Now I don't think there's a way to achieve the syntax you wanted with the unsafe before the scope, but if you put it right after the scope as such it should be about the same:
{ unsafe_scope cur_scope;
return get_value(x); // Performs the check
}
Edit:
I've now noticed Quentin's answer is also a RAII type, just with slightly different semantics, instead of having a global thread_local flag a function just returns if the reference counter is bigger than 0. Also the macro achieves the exact syntax you wanted, although it's also possible with this unsafe_scope by modifying his macro like this:
#define unsafe\
if (unsafe_scope cur_scope; false) {} else
His method uses C++17's if initializer, which lets you initiates a variable in the if statement, but the variable is still initialized in the else block, so it only gets destroyed after the else scope if over.
I am trying to apply the Composite pattern, so I need to create a Leaf class and a Composite class, both inheriting from the same Component class. In order for any of my Components to perform their duty they need to ask help from a single Helper object. We have the following
struct Helper {
void provide_help();
};
struct Component {
Component(Helper* helper)
: m_helper(helper) {
}
virtual void operation() = 0;
// the call_for_help function will be used by subclasses of Component to implement Component::operation()
void call_for_help() {
m_helper->provide_help();
}
private:
Helper* m_helper;
};
And here are two different Leaf subclasses:
struct Leaf1
: Component {
Leaf1(Helper* helper)
: Component(helper) {
}
void operation() override {
call_for_help();
operation1();
}
void operation1();
};
struct Leaf2
: Component {
Leaf2(Helper* helper)
: Component(helper) {
}
void operation() override {
call_for_help();
operation2();
}
void operation2();
};
So far, so good. Now the Composite class is giving me grief. The typical implementation is as follows
struct Composite
: Component {
Composite(Helper* helper)
: Component(helper) {
}
void operation() override {
for (auto el : m_children) el->operation();
}
private:
std::vector<Component*> m_children;
};
which by going through the m_children one by one and calling operation on each essentially calls the helper function multiple times, even though one call is enough for all children. Ideally, if the m_children consisted, say, of a Leaf1 and a Leaf2, I would like somehow the Composite operation to call the helper function only once and then call in succession Leaf1::operation1() and then Leaf2::operation2(). Is there any way to achieve what I need? Alternative designs are welcome. I hope my question makes sense. Thanks in advance!
You want a polymorphic operation but you are adding more responability to the method (calling the helper). It's better to separate these two things.
struct Component {
void call_operation(){
call_for_help();
operation();
}
virtual void operation() = 0;
void call_for_help();
};
Remove the call_for_help() from leaf::operation() (making operation1, operation2 redundant, polymorphism) and the rest should work fine.
You can even hide operation() from your public interface, you'll need friendship with your Composite in that case.
As it could happen at any level, one approach could be to handle this at the level of the helper.
A sketch of the approach would be:
class Helper {
bool composite_help = false;
bool help_provided;
public:
void provide_help() {
if ((composite_help && !help_provided) || !composite_help) {
//TO DO: provide help
help_provided = true;
}
}
void start_composite_help() {
composite_help = true;
help_provided = false;
}
void end_composite_help() {
composite_help = false;
}
};
The principle is that the call for help performed by individual components works as before. But when the composite calls for help, you take preacutions to make sure that the call is performed only once:
void operation() override {
m_helper->start_composite_help();
for (auto el : m_children) el->operation();
m_helper->start_composite_help();
}
As said, this is only a sketch: the code provided as such will not work as soon as you have several levels of composites. So this needs to be improved:
instead of a bool composite_help you'd need a counter, which gets incremented when entering a composite operation and decremented when you exit it. In this case, the counter would go back to 0 (re-enabling help) only when the last level of composte has finished its job.
may be the helper performs different operations to provide help. So you could also imagine to have a "transaction id" that uniquely identifies a group of related operations, and you manage the counter not for the helper overall, in a map of active transactions.
finally, the start/end is not so nice. A RAII helper to the helper could make the whole setup more robust (for example when an exception breaks the normal execution flow.)
I think this problem would be better solved with a combination of Composite and Mediator.
Heads up! I'll show you a different version of the mediator pattern, which is not the same as the canonical version.
It's not of the business of your composite structure to know if a helper was called or not. You'd better do this using some kind of event handler.
Since you have only one helper, you could try like this:
class Helper {
public:
void callHelper() { std::cout << "Helper called" << std::endl; }
};
class Mediator {
private:
std::map<std::string, std::vector<Helper>> subscribers;
int updateLimit = -1;
int currentUpdateCount = 0;
void resetUpdateCount() {
currentUpdateCount = 0;
}
public:
Mediator(){}
void subscribe(std::string evt, Helper helper) {
subscribers[evt].push_back(helper);
}
void update(std::string evt) {
for (auto& h: subscribers[evt]) {
h.callHelper();
}
}
void setUpdateLimit(int i) {
updateLimit = i;
resetUpdateCount();
}
void removeUpdateLimit() {
updateLimit = -1;
resetUpdateCount();
}
int getUpdateLimit() {
return updateLimit;
}
void updateLimited(std::string evt) {
if (updateLimit < 0 || currentUpdateCount < updateLimit) {
update(evt);
currentUpdateCount++;
}
}
};
int main(int argc, const char *argv[])
{
Mediator m;
Helper h1, h2;
m.subscribe("bar", h1);
m.setUpdateLimit(1);
// Will be called only once
m.updateLimited("bar");
m.updateLimited("bar");
m.updateLimited("bar");
m.removeUpdateLimit();
return 0;
}
Using it:
Mediator m;
Helper h1, h2;
m.subscribe("bar", h1);
m.setUpdateLimit(1);
// Will be called only once
m.updateLimited("bar");
m.updateLimited("bar");
m.updateLimited("bar");
m.removeUpdateLimit();
So, here is what you do to integrate this to you composite structure. Remove the helper from you nodes, add the Mediator to the base class:
struct Component {
Component(Mediator& mediator)
: m_helper(mediator) {
}
virtual void operation() = 0;
// the call_for_help function will be used by subclasses of Component to implement Component::operation()
void notify() {
m_mediator->updateFiltered(Component::updateEventName);
}
static std::string updateEventName;
private:
Mediator& m_mediator;
};
std::string Component::updateEventName = "update.composite";
struct Leaf1
: Component {
Leaf1(Helper* helper)
: Component(helper) {
}
void operation() override {
notify();
operation1();
}
void operation1();
};
Using it:
Mediator m;
Helper h;
Composite c(m);
Leaf1 l1(m), l2(m);
c.add(l1);
c.add(l2);
m.subscribe(Component::updateEventName, h);
m.setUpdateLimit(1);
// Will be called only once, even if it has childrens
c.update();
m.removeUpdateLimit();
IMPORTANT: This solution is suboptimal, it has some issues, like you having to pass a mediator instance to every node constructor, but it's just a raw idea for you to work on.
Hope it helps!
I have a scenario where a function accepts a structure (existing, existinghelper) which is just a data holder. but the function which process this data is tightly bound to this data. Now i need to handle extra data for which the structures needs to be extended (to_be_extended, to_be_extended_helper). What is the best way to acheive this?
The present code looks like below:
struct existing
{
int a;
int b;
};
struct existinghelper
{
int aindex;
int bindex;
};
struct to_be_extended
{
existing e;
int c;
};
struct to_be_extended_helper
{
int aindex;
int bindex;
int cindex;
};
void fun1(existing& e)
{
existinghelper(e);
}
EXPECTED: I need the same code (fun1) to work for both extended and existing structures. logically like below
void fun1(existing& e ) // can be <to_be_extended & e> this should support both existing and to_be_extended structure both.
{
existinghelper(e); // or to_be_extended_helper(ee);
//above line should support both existinghelper and to_be_extended_helper structure
both.
/*
//logically it should work like below:
if(type == existing)
make existinghelper object.
else
make to_be_extended_helper object.
The problem is they are not polymorphic and are just data holders.
*/
}
Overload the function for the different argument types:
void fun1(existing& e)
{
...
}
void fun1(to_be_extended& e)
{
...
}
If you have a lot of code that is identical for both functions, and you are trying to avoid code duplication, you can factor the common functionality into a function template.
template<typename T>
void identical_stuff(T& e)
{
...
}
void fun1(existing& e)
{
... non-identical stuff ...
identical_stuff(e);
}
void fun1(to_be_extended& e)
{
... non-identical stuff ...
identical_stuff(e);
}
Make them polymorhic First Choice.
If its not desired add a data member type (possibly integer type) so if type==1
make existinghelper object.
else if type==2
make to_be_extended_helper object.
make to_be_extended extend existing, and add a flag。
struct existing
{
int a, b;
bool isBase;
existing():isBase(true){}
}
struct to_be_extended : public existing
{
int c;
to_be_extended():isBase(false){}
}
func(existing& e)
{
if(e.isBase)
...
else
...
}
As an example, I have this case, in which the classes A and B perform the same expensive calculation, the function expensiveFunction. This function is "pure", in that I can guarantee that it will give the same result given the same input. The client may use both classes (or more similar classes) with the same input, and I would wish that the expensensive function is only calculated once. However, the client may also only use one class for a given input.
Code example:
class A {
public:
A(const InputData& input) {
res = expensiveFunction(input);
}
void foo(); //Use the expensive result
private:
ExpensiveResult res;
};
class B {
public:
B(const InputData& input) {
res = expensiveFunction(input); //Same function as in A
}
double bar(); //Use the expensive result
private:
ExpensiveResult res;
};
int main() {
//Get some input
//...
A a(input);
B b(input);
//Do stuff with a and b
//More input
A a2(otherInput);
//...
}
In some languages, due to referential transparency and memoization, it can safely compute it only once for a given input.
What I have thought of is using some sort factory method/class, or give a function object/functor/supension to the A and B classes that stores the result.
What are some good design ideas to solve this problem?
I own all of the code, so I can change the client or the service classes if necessary.
You can memoize just inside of your function
COutput expensive(CInput input) {
static std::map<CInput, COutput> memoized_result;
auto resit = memoized_result.find(input);
if (resit == memoized_result.end()) {
// ... do calculations
output = expensiveCalculation(input);
resit = memoized_result.insert(std::make_pair(input, output));
}
return resit->second;
}
The result of your computation is stored in the static map (memoized_result), and persisted between function calls.
If input is too expensive to use as a key in the map, you can create a separate class for handling computation result, and share it between all clients:
#include <memory>
using namespace std;
class ExpensiveResult {
public:
ExpensiveResult(int input) {
out_ = input+1;
}
int out_;
};
class BaseCompResultUser {
public:
BaseCompResultUser(const std::shared_ptr<ExpensiveResult>& res) {
res_ = res;
}
private:
std::shared_ptr<ExpensiveResult> res_;
};
class A : public BaseCompResultUser {
public:
A(const std::shared_ptr<ExpensiveResult>& r) : BaseCompResultUser(r) { }
};
class B : public BaseCompResultUser {
public:
B(const std::shared_ptr<ExpensiveResult>& r) : BaseCompResultUser(r) { }
};
int main() {
std::shared_ptr<ExpensiveResult> res(new ExpensiveResult(1));
A a(res);
B b(res);
return 0;
}
This will force sharing computation result between objects.
I think that the object-oriented way of solving it is for the expensiveFunction to be a member function of InputData (or some wrapper of InputData) and then your problem pretty much goes away. You just make ExpensiveResult a mutable cache in InputData:
class InputData {
private:
mutable std::shared_ptr<ExpensiveResult> result_;
public:
InputData() : result_(nullptr) {}
std::shared_ptr<ExpensiveResult> expensiveFunction() const {
if (!result_) {
// calculate expensive result...
result_ = std::make_shared<ExpensiveResult>();
}
return result_;
}
};
The expensive calculation is only done the first time expensiveFunction is called. You might have to add some locking if this is being called in a multi-threaded way.
If ExpensiveFunction does the same thing in A and B, it hardly seems like a true member of either. Why not a function?
int main() {
//Get some input
//...
res = expensiveFunction (input) ;
A a(res);
B b(res);
//Do stuff with a and b
//...
}
I have several CUDA Kernels which are basically doing the same with some variations. What I would like to do is to reduce the amout of code needed. My first thought was to use macros, so my resulting kernels would look like this (simplified):
__global__ void kernelA( ... )
{
INIT(); // macro to initialize variables
// do specific stuff for kernelA
b = a + c;
END(); // macro to write back the result
}
__global__ void kernelB( ... )
{
INIT(); // macro to initialize variables
// do specific stuff for kernelB
b = a - c;
END(); // macro to write back the result
}
...
Since macros are nasty, ugly and evil I am looking for a better and cleaner way. Any suggestions?
(A switch statement would not do the job: In reality, the parts which are the same and the parts which are kernel specific are pretty interweaved. Several switch statements would be needed which would make the code pretty unreadable. Furthermore, function calls would not initialize the needed variables. )
(This question might be answerable for general C++ as well, just replace all 'CUDA kernel' with 'function' and remove '__global__' )
Updated: I was told in the comments, that classes and inheritance don't mix well with CUDA. Therefore only the first part of the answer applies to CUDA, while the others are answer to the more general C++ part of your question.
For CUDA, you will have to use pure functions, "C-style":
struct KernelVars {
int a;
int b;
int c;
};
__device__ void init(KernelVars& vars) {
INIT(); //whatever the actual code is
}
__device__ void end(KernelVars& vars) {
END(); //whatever the actual code is
}
__global__ void KernelA(...) {
KernelVars vars;
init(vars);
b = a + c;
end(vars);
}
This is the answer for general C++, where you would use OOP techniques like constructors and destructors (they are perfectly suited for those init/end pairs), or the template method pattern which can be used with other languages as well:
Using ctor/dtor and templates, "C++ Style":
class KernelBase {
protected:
int a, b, c;
public:
KernelBase() {
INIT(); //replace by the contents of that macro
}
~KernelBase() {
END(); //replace by the contents of that macro
}
virtual void run() = 0;
};
struct KernelAdd : KernelBase {
void run() { b = a + c; }
};
struct KernelSub : KernelBase {
void run() { b = a - c; }
};
template<class K>
void kernel(...)
{
K k;
k.run();
}
void kernelA( ... ) { kernel<KernelAdd>(); }
Using template method pattern, general "OOP style"
class KernelBase {
virtual void do_run() = 0;
protected:
int a, b, c;
public:
void run() { //the template method
INIT();
do_run();
END();
}
};
struct KernelAdd : KernelBase {
void do_run() { b = a + c; }
};
struct KernelSub : KernelBase {
void do_run() { b = a - c; }
};
void kernelA(...)
{
KernelAdd k;
k.run();
}
You can use device functions as "INIT()" and "END()" alternative.
__device__ int init()
{
return threadIdx.x + blockIdx.x * blockDim.x;
}
Another alternative is to use function templates:
#define ADD 1
#define SUB 2
template <int __op__> __global__ void caluclate(float* a, float* b, float* c)
{
// init code ...
switch (__op__)
{
case ADD:
c[id] = a[id] + b[id];
break;
case SUB:
c[id] = a[id] - b[id];
break;
}
// end code ...
}
and invoke them using:
calcualte<ADD><<<...>>>(a, b, c);
The CUDA compiler does the work, build the different function versions and removes the dead code parts for performance optimization.