Is pointer conversion expensive or not?

Is the pointer conversion considered expensive? (like how many cpu cycles it takes to convert a pointer / address) especially when you need to do this quite often, for example (just an example showing the freqency scale, I know there are better ways for these specific cases)

unsigned long long *x;
/* fill data to x*/

for (int i = 0; i < 1000*1000*1000; i++)
{

    A[i]=foo((unsigned char*)x+i);

};

      

+3


source to share


4 answers


(e.g. how many cpu cycles it takes to convert a pointer / address)

Most machine languages ​​only have 1 pointer "type" and so there is nothing convertible between them. Keep in mind that C ++ types only really exist at compile time.

The real problem is that such code might violate strict alias rules. You can read more about this elsewhere, but essentially the compiler will either produce the wrong code with undefined behavior, or be forced to make conservative assumptions and therefore produce slower code. (note that char*

friends are also somewhat exempt from the undefined behavior part)



Optimizers are often forced to make conservative assumptions about variables in the presence of pointers. For example, a persistent propagation process that knows the value of x is 5 will not be able to continue to use this information after assigning another variable (eg * y = 10), as it might be that * y is an alias for x. This can occur after an assignment such as y = & x.

As an effect of the assignment to * y, the value of x will also be changed, so propagating the information that x is 5 in expressions following * y = 10 is potentially incorrect (if * y is indeed an alias for x). However, if we have information about pointers, the continuous propagation process can make a query like: can x - alias * y? Then, if the answer is no, x = 5 can be safely propagated. Another optimization caused by anti-aliasing is code reordering. If the compiler decides that x is not flattened with * y, then code that uses or modifies the value of x may be carried over before assigning * y = 10 if this improves scheduling or allows for more loop optimization.

To provide such optimization in a predictable manner, the ISO standard for the C programming language (including its newer version of C99, see section 6.5, paragraph 7) indicates that it is illegal (with a few exceptions) for pointers of different types to reference the same cell memory. This rule, known as a "strong alias", sometimes produces dramatic performance gains, [1] but has been known to break some other valid code. Several software projects deliberately violate this part of the C99 standard. For example, Python 2.x did this to implement reference counting, [2] and the necessary changes to the underlying object structures in Python 3 to enable this optimization. The Linux kernel does this because strict pseudo-downgrading causes inline optimization problems.[3] In such cases, when compiling with gcc, the -fno-strict-aliasing option is invoked to prevent unwanted optimizations that could lead to unexpected code. [Edit]

http://en.wikipedia.org/wiki/Aliasing_(computing)#Conflicts_with_optimization

What is a strict alias rule?

+9


source


In whatever architecture you are likely to come across, all pointer types have the same representation, and therefore converting between different pointer types representing the same address is not time-consuming. This applies to all pointer conversions in C.

In C ++, some pointer conversions have a cost and some don't:



  • reinterpret_cast

    and const_cast

    (or an equivalent C-style like the one asked in the question) and converting to or from void*

    will just reinterpret the pointer value at no cost.
  • Conversion between pointer-to-base-class and pointer-to-derived (either implicitly, or through static_cast

    C-style casting or equivalent) may require adding a fixed offset to the pointer value if multiple base classes exist.
  • dynamic_cast

    will do a nontrivial amount of work to find a pointer value based on the dynamic type of the object it points to.

Historically, some architectures (eg PDP-10) have had different representations for pointer to byte and pointer to word; there may be some execution cost for the conversions.

+6


source


unsigned long long *x;
/* fill data to x*/

for (int i = 0; i < 1000*1000*1000; i++)
{

    A[i]=foo((unsigned char*)x+i); // bad cast

}

      

Remember that the machine only knows addresses, data and memory code. Everything else (like types, etc.) is only known to the compiler (which helps the programmer) and this does all the pointer arithmetic, only the compiler knows the size of each type .. so on and so forth.

At runtime, there are no machine cycles wasted when converting from one pointer type to another, because the conversion is not done at runtime. All pointers are treated as 4 bytes (on a 32-bit machine) no more and no less.

+1


source


It all depends on your basic equipment.

On most machine architectures, all pointers are pointers to bytes, and the conversion between byte pointer and byte pointer is no-op. In some architectures, converting a pointer may in some cases require additional manipulations (for example, there are machines that work with words based on addresses, and converting a pointer to a byte pointer or vice versa will require additional manipulations).

Also, this is generally not a safe method, because the compiler cannot check for what you are doing and you can overwrite data that you were not expecting.

0


source







All Articles