Boost logo

Boost Users :

From: Erik (sigra_at_[hidden])
Date: 2007-10-11 08:00:50


Erik skrev:
> I did some tests and got the exact same results for the following use
> of BOOST_FOREACH (and the corresponding use of my macro and a
> handcoded loop):
> //////////////////////////////////////////////////////
> #include <boost/foreach.hpp>
>
> #include <vector>
>
> void f(float);
> struct A {
> void g() const;
> std::vector<float> const v;
> };
>
> void A::g() const {
> BOOST_FOREACH(float i, v)
> f(i);
> }
> /////////////////////////////////////////////////////
Of course I got the exact same results with this code, because v is the
first member of A, so A::v has the same address as A. When I realized
this I modified the testcase:

//////////////////////////////////////////////////////

#include <boost/foreach.hpp>

#include <vector>

void f(float);
struct A {
   void g() const;
   char name[52];
   std::vector<float> const v;
};

void A::g() const {
   BOOST_FOREACH(float i, v)
      f(i);
}
//////////////////////////////////////////////////////

Unfortunately it does not look so good for BOOST_FOREACH after this
modification. It will increase to 24 instructions, while the handcoded
is still only 21. I created a script (attached) to test the examples
systematically with different compiler versions and optimization levels.
Here are the results that it gave me:
Optimizations: O3 O2 Os
handcoded:
   parameter:
      g++-4.2.0: 21 21 20
      g++-4.1.2: 21 21 20
   member:
      g++-4.2.0: 21 21 20
      g++-4.1.2: 21 21 20
   member_with_local:
      g++-4.2.0: 21 21 20
      g++-4.1.2: 21 21 20
iterate_vector:
   parameter:
      g++-4.2.0: 21 21 20
      g++-4.1.2: 21 21 20
   member:
      g++-4.2.0: 21 21 20
      g++-4.1.2: 21 21 20
   member_with_local:
      g++-4.2.0: 21 21 20
      g++-4.1.2: 21 21 20
BOOST_FOREACH:
   parameter:
      g++-4.2.0: 21 31 57
      g++-4.1.2: 28 35 90
   member:
      g++-4.2.0: 24 32 58
      g++-4.1.2: 29 36 91
   member_with_local:
      g++-4.2.0: 24 32 58
      g++-4.1.2: 29 36 91

If you want to try it yourself, put the script in an empty directory and
run from there; it will create some files. After running it, it may be
interesting to compare the generated code, for example:
diff -dU2 iterate_vector-member-g++-4.2.0-O3.s
BOOST_FOREACH-member-g++-4.2.0-O3.s|kompare -


#! /bin/sh

ITERATIONS="0 1 2"
ITERATION_NAMES=(handcoded iterate_vector BOOST_FOREACH)
ITERATION_CODES=(\
"
   std::vector<float>::const_iterator const v_end = v.end();
   for (std::vector<float>::const_iterator it = v.begin(); it != v_end; ++it)
      f(*it);" \
"
#define iterate_vector_const(value_type, it, v) \\
   for \\
      (struct { \\
          std::vector<value_type>::const_iterator current; \\
          std::vector<value_type>::const_iterator const end; \\
          value_type const & operator*() {return *current;} \\
       } it = {v.begin(), v.end()}; \\
       it.current != it.end; \\
       ++it.current) \\

   iterate_vector_const(float, it, v)
      f(*it);" \
"
   BOOST_FOREACH(float i, v)
      f(i);")

EXAMPLES="0 1 2"
EXAMPLE_NAMES=(parameter member member_with_local)
EXAMPLE_CODES=(\
"
void g(const std::vector<float> & v) {" \
"
struct A {
   void g() const;
   char name[52];
   std::vector<float> const v;
};

void A::g() const {" \
"
struct A {
   void g() const;
   char name[52];
   std::vector<float> const m_v;
};

void A::g() const {
   std::vector<float> const & v = m_v;
")

COMPILER_VERSIONS="4.2.0 4.1.2"
OPTIMIZATOINS="3 2 s"

unset TABLE_HEADER
for optimization in $OPTIMIZATOINS; do
        TABLE_HEADER="$TABLE_HEADER O$optimization"
done
echo "Optimizations: $TABLE_HEADER"
for iteration in $ITERATIONS; do
        echo ${ITERATION_NAMES[$iteration]}:
        for example in $EXAMPLES; do
                NAME=${ITERATION_NAMES[$iteration]}-${EXAMPLE_NAMES[$example]}
                IN=$NAME.cc
                rm -f $IN
                echo "void f(float);" >> $IN
                echo "#include <boost/foreach.hpp>" >> $IN
                echo "#include <vector>" >> $IN
                echo "${EXAMPLE_CODES[$example]}" >> $IN
                echo "${ITERATION_CODES[$iteration]}" >> $IN
                echo "}" >> $IN
                echo " ${EXAMPLE_NAMES[$example]}:"
                for compiler_version in $COMPILER_VERSIONS; do
                        MESSAGE=g++-$compiler_version:
                        for optimization in $OPTIMIZATOINS; do
                                OUT=$NAME-g++-$compiler_version-O$optimization.s
                                g++-$compiler_version -Wall -Wextra -O$optimization -S $IN -o $OUT
                                MESSAGE="$MESSAGE $(egrep -v "^([ ]*\\.|_)" $OUT|wc -l)"
                        done
                        echo " $MESSAGE"
                done
        done
done


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net