Efficiently preventing duplicate accesses - c++

I have a statement computing a multiply-accumulate operation that looks something like this:
return A->set(A->get() + B->get() * C->get());
Now, A, B, and C may not be unique, and I want to minimize redundant get()s. The only way I can think of optimizing this is with
if (A == B && B == C) {
double a = A->get();
return A->set(a + a * a);
} else if (A == B) {
double a = A->get();
return A->set(a + a * C->get());
} else if (A == C) {
double a = A->get();
return A->set(a + B->get() * a);
} else if (B == C) {
double b = B->get();
return A->set(A->get() + b * b);
} else {
return A->set(A->get() + B->get() * C->get());
}
Is there a more efficient way? What about generalizing this to more than three arguments??

You can store them in a map. The solution can be extended easily to arbitrarily many pointers, but I've used three here for concreteness.
std::unordered_map<MyType *, double> computed_values;
for (MyType *p: {A, B, C}) {
if (computed_values.find(p) == computed_values.end()) {
computed_values[p] = p->get();
}
}
double result = computed_values[A] + computed_values[B] * computed_values[C];
A->set(result);
As others have pointed out, make sure you profile to make sure this is actually worth the overhead of std::unordered_map lookups.

Assuming get() methods are really costly to the extent of producing measurable performance difference,
double a,b,c;
a = A->get();
b = (B==A?a:B->get());
c = (C==B?b:(C==A?a:c->get()));
return A->set(a+b*c);

Assuming the get() methods are reasonably cheap, you'd be better off just doing:
return A->set(A->get() + B->get() * C->get());
The other approach simply inserts a bunch of conditional jumps into your code, which could easily end up being more expensive than the original code.

Related

Best practice about for loop with an const if inside in cpp

For example.
if (bitwidth == 0) {
for (int bhwc = 0; bhwc < B * H * W * C; ++bhwc) {
p_res[bhwc] = res_f32[bhwc];
}
} else {
for (int bhwc = 0; bhwc < B * H * W * C; ++bhwc) {
p_res[bhwc] = res_f32[bhwc].toint(bitwidth, fracwidth);
}
}
vs
for (int bhwc = 0; bhwc < B * H * W * C; ++bhwc) {
if (bitwidth == 0) {
p_res[bhwc] = res_f32[bhwc];
} else {
p_res[bhwc] = res_f32[bhwc].toint(bitwidth, fracwidth);
}
}
The second one is more readable and maintainable, but it's maybe slower. Is there any better method?(As you can see, The outside for loop may be very complex, with 4 dimension...
The performance implications are insignificant, and every modern compiler should be able to optimize that to avoid the branch in the middle of the loop.
However, this shows an interesting problem, and serves as a great argument against using for loops. They're a very low-level construct and should be avoided where the alternatives can be applied. In this case, using them forces you to choose between a clean-looking implementation (with potential performance drawback) and a technically-better one, but stylistically suboptimal.
Your two operations can be described in terms of two generic operations: copy and transform. You can write the algorithm in terms of them, like so:
if (bitwidth == 0) {
using std::copy_n;
copy_n(res_f32, B * H * W * C, p_res);
} else {
transform_n(res_f32, B * H * W * C, p_res, [=](auto const& x){ return x.toint(bitwidth, fracwidth); });
}
Unfortunately, there's no std::transform_n, but you can make one. Alternatively, and much better, if your B*H*W*C term can be stored in terms of the container, it'd be best to express that as a view or the container's begin/end directly, thus enabling the use of the automatic (non-_n) copy/transform instead.
This is not just more readable, but expresses the logic in the commonly-understood terms of standard operations, leaves less room for errors and allows much easier changes of underlying containers, operations, potential parallelism and overall maintainability.

How to safely compare two unsigned integer counters?

We have two unsigned counters, and we need to compare them to check for some error conditions:
uint32_t a, b;
// a increased in some conditions
// b increased in some conditions
if (a/2 > b) {
perror("Error happened!");
return -1;
}
The problem is that a and b will overflow some day. If a overflowed, it's still OK. But if b overflowed, it would be a false alarm. How to make this check bulletproof?
I know making a and b uint64_t would delay this false-alarm. but it still could not completely fix this issue.
===============
Let me clarify a little bit: the counters are used to tracking memory allocations, and this problem is found in dmalloc/chunk.c:
#if LOG_PNT_SEEN_COUNT
/*
* We divide by 2 here because realloc which returns the same
* pointer will seen_c += 2. However, it will never be more than
* twice the iteration value. We divide by two to not overflow
* iter_c * 2.
*/
if (slot_p->sa_seen_c / 2 > _dmalloc_iter_c) {
dmalloc_errno = ERROR_SLOT_CORRUPT;
return 0;
}
#endif
I think you misinterpreted the comment in the code:
We divide by two to not overflow iter_c * 2.
No matter where the values are coming from, it is safe to write a/2 but it is not safe to write a*2. Whatever unsigned type you are using, you can always divide a number by two while multiplying may result in overflow.
If the condition would be written like this:
if (slot_p->sa_seen_c > _dmalloc_iter_c * 2) {
then roughly half of the input would cause a wrong condition. That being said, if you worry about counters overflowing, you could wrap them in a class:
class check {
unsigned a = 0;
unsigned b = 0;
bool odd = true;
void normalize() {
auto m = std::min(a,b);
a -= m;
b -= m;
}
public:
void incr_a(){
if (odd) ++a;
odd = !odd;
normalize();
}
void incr_b(){
++b;
normalize();
}
bool check() const { return a > b;}
}
Note that to avoid the overflow completely you have to take additional measures, but if a and b are increased more or less the same amount this might be fine already.
The posted code actually doesn’t seem to use counters that may wrap around.
What the comment in the code is saying is that it is safer to compare a/2 > b instead of a > 2*b because the latter could potentially overflow while the former cannot. This particularly true of the type of a is larger than the type of b.
Note overflows as they occur.
uint32_t a, b;
bool aof = false;
bool bof = false;
if (condition_to_increase_a()) {
a++;
aof = a == 0;
}
if (condition_to_increase_b()) {
b++;
bof = b == 0;
}
if (!bof && a/2 + aof*0x80000000 > b) {
perror("Error happened!");
return -1;
}
Each a, b interdependently have 232 + 1 different states reflecting value and conditional increment. Somehow, more than an uint32_t of information is needed. Could use uint64_t, variant code paths or an auxiliary variable like the bool here.
Normalize the values as soon as they wrap by forcing them both to wrap at the same time. Maintain the difference between the two when they wrap.
Try something like this;
uint32_t a, b;
// a increased in some conditions
// b increased in some conditions
if (a or b is at the maximum value) {
if (a > b)
{
a = a-b; b = 0;
}
else
{
b = b-a; a = 0;
}
}
if (a/2 > b) {
perror("Error happened!");
return -1;
}
If even using 64 bits is not enough, then you need to code your own "var increase" method, instead of overload the ++ operator (which may mess your code if you are not careful).
The method would just reset var to '0' or other some meaningfull value.
If your intention is to ensure that action x happens no more than twice as often as action y, I would suggest doing something like:
uint32_t x_count = 0;
uint32_t scaled_y_count = 0;
void action_x(void)
{
if ((uint32_t)(scaled_y_count - x_count) > 0xFFFF0000u)
fault();
x_count++;
}
void action_y(void)
{
if ((uint32_t)(scaled_y_count - x_count) < 0xFFFF0000u)
scaled_y_count+=2;
}
In many cases, it may be desirable to reduce the constants in the comparison used when incrementing scaled_y_count so as to limit how many action_y operations can be "stored up". The above, however, should work precisely in cases where the operations remain anywhere close to balanced in a 2:1 ratio, even if the number of operations exceeds the range of uint32_t.

Boolean logic, If statement reduction

Probably a very simple question but I'm interested in what options there are. I have three conditions each of which should produce a different output
// special cases
if(!A && B)
return -1;
if(A && !B)
return 1;
if(!A && !B)
return 0;
// general case
return someOtherFunction(x, y);
Which I can get down to -
if(!A) {
if(!B)
return 0;
return -1;
}
if(A && !B)
return 1;
return someOtherFunction(x, y);
Can I simplify this further? This is in C++ so I am limited to using language specific operators and functions (including STL) etc.
return (!A ? (!B ? 0 : -1) : (!B ? 1 : someOtherFunction(x, y)));
This is using nested ternary operator.
Use look-up table:
int lookup[2][2] = {
{ 0, -1}
, { 1, 100}
};
...
bool A, B;
A = ...
B = ...
...
int res = lookup[A][B];
// When A && B, call other function
return res != 100 ? res : someOtherFunction(a, b);
Note: If A and B are not Boolean, convert them to logical values with the double-negation trick:
return lookup[!!A][!!B];
I would suggest you to keep it as is for the sake of readability and understanding by the fellow programmer (which might be you). Don't optimize unnecessarily unless really needed. In this case, you don't get any real advantage.
One thing you could do is to store result of A and B into variables (if they are function calls).
So interestingly the case if (A and B) is not defined.
I would use following solution, since boolean can be converted to ints.
return A - B;
Edit: the original question changed. In that case I would do:
if (!A or !B)
return A - B;
return someOtherFunction(A, B);

Object-oriented API for equations

Let's take the Quadratic equation as an example:
a x^2 + b x + c = 0
This equation can be viewed as describing a relation between the values a, b, c, and x. Given three of those, you can calculate the fourth. The four possibilities are:
a = - (b x + c) / x^2
b = - (a x^2 + c) / x
c = - x (a x + b)
x = [-b +- sqrt(b^2 - 4 a c)] / (2 a)
Here's one approach to representing this equation. Given the following class:
class Quadratic
{
public:
double a; bool HasA = false; void A(double a_) { a = a_; HasA = true; }
double b; bool HasB = false; void B(double b_) { b = b_; HasB = true; }
double c; bool HasC = false; void C(double c_) { c = c_; HasC = true; }
double x; bool HasX = false; void X(double x_) { x = x_; HasX = true; }
// a = - (b x + c) / x^2
double A()
{
if (HasB == false) throw domain_error("B not set");
if (HasC == false) throw domain_error("C not set");
if (HasX == false) throw domain_error("X not set");
if (x == 0.0) throw domain_error("X cannot be 0.0");
return - (b*x + c) / (x*x);
}
// x = [-b +- sqrt(b^2 - 4 a c)] / (2 a)
vector<double> X()
{
if (HasA == false) throw domain_error("A not set");
if (HasB == false) throw domain_error("B not set");
if (HasC == false) throw domain_error("C not set");
if (a == 0.0) throw domain_error("A cannot be 0.0");
return
{
(-b + sqrt(b*b - 4 * a*c)) / (2 * a),
(-b - sqrt(b*b - 4 * a*c)) / (2 * a)
};
}
// b = - (a x^2 + c) / x
// ...
// c = - x (a x + b)
// ...
};
We can find x as follows. Set A, B, and C:
obj.A(2.3);
obj.B(3.4);
obj.C(1.2);
There might be two values for X so iterate through the result:
for each (auto elt in obj.X()) cout << elt << endl;
If any of the dependent values are not set, a domain_error exception is thrown.
Similarly, to find A, we set B, C, and X:
obj.B(1.2);
obj.C(2.3);
obj.X(3.4);
and display the result:
cout << obj.A() << endl;
My question is, are there other approaches to representing and working with equations in an object-oriented language? Is there a more idiomatic approach than the above?
The title of your question says:
Object-oriented API for equations
However, there is nothing object-oriented about your code example, at least not with the established definitions of "object-oriented programming" I know. You have no virtual functions, so it's not object-oriented.
Bjarne Stroustrup's FAQ "What is "OOP" and what's so great about it?" says (emphasis added by me):
In the context of C++ [...] it means programming using class hierarchies and virtual
functions to allow manipulation of objects of a variety of types
through well-defined interfaces and to allow a program to be extended
incrementally through derivation.
The Standard C++ FAQ (which also quotes from the first source), answers "Are virtual functions (dynamic binding) central to OO/C++?" like this:
Without virtual functions, C++ wouldn’t be object-oriented.
Therefore,
My question is, are there other approaches to representing and working
with equations in an object-oriented language?
The answer to that should be that mathematical computations and object-orientation programming usually do not mix well. Object orientation is all about choosing the concrete implementation of an abstract operation at run-time. You may, for example, choose a different algorithm with the same input and output based on the user's choice at run-time. This could be done with virtual functions. Still, the object-orientation would happen at a higher level of your application, and the computation itself would not be object-oriented.
Is there a more idiomatic approach than the above?
Yes, generic programming, i.e. templates.
All the code you presented works with double values. What if I want to use it with float, std::complex<double> or a even a custom BigNumber class?
With templates, you can write generic code with concrete implementations chosen at compile-time.
First of all, let's make your original code compilable:
#include <vector>
#include <stdexcept>
#include <math.h>
class Equation
{
public:
bool HasA;
bool HasB;
bool HasC;
bool HasX;
double a;
double b;
double c;
double x;
double A()
{
if (!HasB) throw std::domain_error("B not set");
if (!HasC) throw std::domain_error("C not set");
if (!HasX) throw std::domain_error("X not set");
if (x == 0.0) throw std::domain_error("X cannot be 0.0");
return - (b*x + c) / (x*x);
}
// x = [-b +- sqrt(b^2 - 4 a c)] / (2 a)
std::vector<double> X()
{
if (!HasA) throw std::domain_error("A not set");
if (!HasB) throw std::domain_error("B not set");
if (!HasC) throw std::domain_error("C not set");
if (a == 0.0) throw std::domain_error("A cannot be 0.0");
return
{
(-b + sqrt(b*b - 4 * a*c)) / (2 * a),
(-b - sqrt(b*b - 4 * a*c)) / (2 * a)
};
}
// b = - (a x^2 + c) / x
// ...
// c = - x (a x + b)
// ...
};
int main()
{
Equation e;
std::vector<double> v = e.X();
}
(I've fixed the == false comparisons, which are almost always bad style, but there is more work to do from a C++ coding quality POV, e.g. making the member variables private.)
The problem is that this whole thing only works for doubles. If you try to use it with ints, here's what happens:
int main()
{
Equation e;
std::vector<int> v = e.X();
}
Result:
error C2440: 'initializing' : cannot convert from
'std::vector<double,std::allocator<_Ty>>' to 'std::vector<int,std::allocator<_Ty>>'
Here's how you can turn your class into a template: add template <class T> on top and replace every double with T (and add two static_casts to tell the compiler that you agree with a narrowing conversion which may happen due to sqrt's return type):
#include <vector>
#include <stdexcept>
#include <math.h>
template <class T>
class Equation
{
public:
bool HasA;
bool HasB;
bool HasC;
bool HasX;
T a;
T b;
T c;
T x;
T A()
{
if (!HasB) throw std::domain_error("B not set");
if (!HasC) throw std::domain_error("C not set");
if (!HasX) throw std::domain_error("X not set");
if (x == 0.0) throw std::domain_error("X cannot be 0.0");
return - (b*x + c) / (x*x);
}
// x = [-b +- sqrt(b^2 - 4 a c)] / (2 a)
std::vector<T> X()
{
if (!HasA) throw std::domain_error("A not set");
if (!HasB) throw std::domain_error("B not set");
if (!HasC) throw std::domain_error("C not set");
if (a == 0.0) throw std::domain_error("A cannot be 0.0");
return
{
static_cast<T>((-b + sqrt(b*b - 4 * a*c)) / (2 * a)),
static_cast<T>((-b - sqrt(b*b - 4 * a*c)) / (2 * a))
};
}
// b = - (a x^2 + c) / x
// ...
// c = - x (a x + b)
// ...
};
int main()
{
Equation<int> e;
std::vector<int> v = e.X();
}
Of course, this is only half of the story, because chances are very high that you do not want to allow integral types anyway, only floating-point types like double or float (or custom floating-point types). The result of sqrt(2) truncated to 1 is rarely desirable.
To keep your code generic but prevent such problems, read up on static assertions for compile-time checks, restricting your template to particular types. std::is_floating_point may be useful, too. See also the following recent question on SO:
Getting std::complex<double> to pass std::is_floating_point test
And remember, nothing of this has anything to do with object-oriented programming.

Removing Virtual Inheritance

I am working on an embedded project I am trying to remove a virtual number class that has + / - * implemented. removing this class saves a lot of code space so I have replaced + with the following function,
if (BASE(h)->type() == FLOAT && BASE(v)->type() == FLOAT)
{
res = FLOAT(h)->floatValue() + FLOAT(v)->floatValue();
}
else if (BASE(h)->type() == INTEGER && BASE(v)->type() == INTEGER)
{
res = INTEGER(h)->intValue() + INTEGER(v)->intValue();
}
else if (BASE(h)->type() == INTEGER && BASE(v)->type() == FLOAT)
{
res = INTEGER(h)->floatValue() + FLOAT(v)->floatValue();
}
else
{
res = FLOAT(h)->floatValue() + INTEGER(v)->floatValue();
}
Is there a less uglier way to achieve this? cause I have to use the same scheme for other ops and comparison?
#define GETFLOAT(arg) (BASE(arg)->type() == INTEGER ? INTEGER(arg)->floatValue() : FLOAT(arg)->floatValue())
switch(BASE(h)->type()) {
case INTEGER:
if (BASE(v)->type() == INTEGER) {
res = INTEGER(h)->intValue() + INTEGER(v)->intValue();
break;
}
case FLOAT:
res = GETFLOAT(h) + GETFLOAT(v);
}
This actually branches on the type of h twice, but only in the case that (you say in a comment elsewhere) is expensive anyway, the floating-point op. You could avoid that with a goto, but I'm not going to have that argument again. Something like:
switch(BASE(h)->type()) {
case INTEGER:
if (BASE(v)->type() == INTEGER) {
res = INTEGER(h)->intValue() + INTEGER(v)->intValue();
goto finished; // or better: return res;
}
hvalue = INTEGER(h)->floatValue()
break;
case FLOAT:
hvalue = FLOAT(h)->floatValue();
}
res = hvalue + GETFLOAT(v);
finished:
As with Howard's answer, if BASE() or type() is expensive then you could calculate the answer for each argument once, even though it's used twice.
What about doing it in two steps?
isInt1 = BASE(h)->type()==INTEGER;
isInt2 = BASE(v)->type()==INTEGER;
if (isInt1 && isInt2)
op1 = INTEGER(h)->intValue();
op2 = INTEGER(h)->intValue();
res = op1 + op2;
else {
op1 = isInt1 ? (FLOAT(h)->floatValue()) : (INTEGER(h)->floatValue());
op2 = isInt2 ? (FLOAT(v)->floatValue()) : (INTEGER(v)->floatValue());
res = op1 + op2;
}
I recommend reconsidering your architecture. How much have you saved with this approach, and how much has it cost in performance? Your new approach appears pushes everything to a float (you didn't show the declaration of res, which I presume is float res;.
Examine what this fix does to something like (a+b)*c, where each of a, b, and c are (were) integers. With this fix at hand, you now have a float times an int, which is a lot more expensive computationally than an int times an int.
I suggest using templates and letting C++ type system handle as much of the conversion as possible. This lets you use disparate storage types that don't have to have common virtual base class.
You can also cut down on program size by implementing only one of int+float versus float+int (and similarly with int*float versus float*int). Temporarily implement both int+float and float+int, but intentionally make one raise a compile-time error. Flip the order of the operands where you get failures.