[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference hydra::axp-developer

Title:Alpha Developer Support
Notice:[email protected], 800-332-4786
Moderator:HYDRA::SYSTEM
Created:Mon Jun 06 1994
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:3722
Total number of notes:11359

3172.0. "COMPUTEC GmbH Software - Point 19446" by RDGENG::ASAP () Mon Feb 10 1997 06:52

    Company Name :  COMPUTEC GmbH Software - Point 19446
    Contact Name :  Wolfgang Haefelinge
    Phone        :  +49 721 98160106
    Fax          :  +49 721 98160 129
    Email        :  [email protected]
    Date/Time in :  10-FEB-1997 11:51:33
    Entered by   :  Nick Hudson
    SPE center   :  REO

    Category     :  UNIX
    OS Version   :  4.0
    System H/W   :  Alpha


    Brief Description of Problem:
    -----------------------------

	I`m  using your cxx compiler (cxx 5.5) to compile
	my applications. Although your compiler is pretty
	fast, I discovered a big performence problem when
	using templates: The same  application needs on a
	SPARC 20 (50MHz,64MB) running g++ 2.7.2 about 25% 
	the  time  to  get it compiled and linked as on a
	alpha (300MHz,256MB) using cxx. That is definetly
	not a argument to buy an alpha for development!!!

	The  problem  is  that  the compiler instantiates
	templates at *link time*. My  question is how can 
	I force the compiler to  instantiate templates at
	compile time?

	Don't missunderstand me, I **don't** want that the
	compiler writes something into the `cxx_repository'
	at compile time;I want the compiler to instantiate
	templates into the object code. 

Environment:
	OS  : digial unix 4.0 on alpha
	C++ : cxx 5.5

T.RTitleUserPersonal
Name
DateLines
3172.1KZIN::HUDSONThat's what I thinkMon Feb 10 1997 09:44242
From:	DEC:.REO.REOVTX::HUDSON       "[email protected] - UK Software
Partner Engineering 830-4121" 10-FEB-1997 14:43:18.13
To:	nm%vbormc::"[email protected]"
CC:	HUDSON
Subj:	RE:POINT No 19446  C++   template instantiation 

Hello Wolfgang Haefelinge

Thanks for your question on C++ template instantiation.

By default, the C++ compiler does auto-instantiation (the "-pt" switch).  As
you've found, this can be slow if (usually on the first time) the
cxx_repository directory has to be created and populated.

When you use auto-instantiation, then the cxx_repository is used in two ways. 
First, the compiler will put "source code" in there for any templates it
encounters.  Second, when the linker runs, if it comes across any undefined
symbols, for example something like "myclass<int>::myclass()", then it asks the
C++ compiler to run again and generate the necessary code.  This means the c++
compiler looks in cxx_repository for the files needed to build a template
instance of the type needed, compiles them, puts the object code in
cxx_repository, and then gets the linker to run again.

I have seen people say that this can be very slow, and the response from the
engineering team is (1) Yes we know and we're going to make it better, and (2)
bear in mind that after a few iterations, you probably will have the necessary
modules compiled in the cxx_repository directory so that subsequent builds
should be quicker (the compiler only needs to instantiate a "myclass<int>"
once, and then that can be used many times.

But, to answer your question specifically, it is possible to force the compiler
to generate template instances on its first pass.  In fact this used to be the
only way to get templates working before auto-instantiation appeared (in 5.3 of
C++ I think).  The disadvantage is that you need to know ahead of time what
template instances you need.  

Below I include two things.  First, a memo I wrote describing how you can do
manual template instantiation.  This was written before auto-instantiation was
available.

Second, I include a set of files I've used on Unix to show how the same program
can be built with and without auto-instantation.  This is a contrived and very
small case, but it does seem faster when you do manual instantiation.

I hope this is helpful to you

Regards
Nick Hudson
Digital Software Partner Engineering

================================================================================
DEC C++ does not presently have automated template instantiation; it relies on
the programmer providing information to the compiler to indicate which
functions are required.  Chapter 4 of the "Using DEC C++" manual describes the
ways in which a programmer can provide information to instruct the compiler to
instantiate particular forms of class or function templates.  Briefly, there
are three ways in which template functions are instantiated:

1. Function templates that have internal linkage

   Any function that is static or inline has "internal linkage" (i.e. is
   local to the module in question) and will be automatically instantiated
   by the compiler when it sees a reference to the function.

   This is viable when all of the template source code is in the same module as
   the instantiations of the functions, so will be practical in a minority of
   cases.

   For example, in the following case, the compiler will automatically
   instantiate "int" and "float" versions of the "add" function:

	#include <iostream.h>
	template<class T>
	inline T add(T x, T y)
	{
	        return (x+y);
	}
	main()
	{
	        int     a,b,c;
	        float   x,y,z;

	        a = 1; b = 2;
	        x = 1.2; y = 2.0;
	
	        c = add(a,b);
	        z = add(x,y);
	
	        cout << c << "  " << z << endl;
	}

	

2. Compiler switch "-define_templates"

   For functions that don't have internal linkage, a compiler qualifier can be
   used to force instantiation.  For example, in the program above, if the
   "add" function were not specified as "inline", the compiler could still be
   made to instantiate "int" and "float" versions of "add" if the compiler
   switch were used.

   This is viable when all of the template source code is available at the time
   the compiler is parsing the module contain the function instantiations.


3. Pragma "#pragma define_template"

   This pragma can be used to tell the compiler that a particular form of the
   function or class template needs to be instantiated.  For example:

   // This is add.cxx
   template <class T>
   T add(T x, T y)
   {
   	return (x + y);
   }
   #pragma define_template add<int>
   #pragma define_template add<float>

   This mechanism allows full control over which versions of the template are
   instantiated, but means that the programmer has specifically to use the
   pragma rather than rely on the compiler to work out which instantiations are
   required.


[Although I've used the term "template function" in the above, template classes
can be instantiated in the same way]

Typically we find that customers are able to use these mechanisms (mostly
#pragma) to build their applications.  However, it does mean that templates are
difficult to use, and in many cases the organisation of source modules has to
be changed to accommodate the deficiencies in the compiler.

Work is being done by the C++ engineering team to include automated template
instantiation in a future release of the compiler, which will ease these
problems.

================================================================================

////////////////////////////////////////////////////////////////////////////////
///////////// Makefile ///////////////

prog_auto : prog.cxx pair.h pair.cxx
        cxx -o prog_auto -pt prog.cxx

prog_noauto : prog.cxx pair.h pair.cxx
        cxx -c -o pair.o -DNOAUTO pair.cxx
        cxx -o prog_noauto -nopt -DNOAUTO prog.cxx pair.o


////////////////////////////////////////////////////////////////////////////////
// pair.h
#ifndef __PAIR_H
#define __PAIR_H
template<class T>
class pair {
        T       item1;
        T       item2;

public:
        pair();
        pair(const T p1, const T p2);
void    first() const;
void    second() const;
};
#endif

////////////////////////////////////////////////////////////////////////////////
// pair.cxx
#include <iostream.h>
#include "pair.h"

template<class T>
pair<T>::pair()
{
        item1 = (T)NULL;
        item2 = (T)NULL;
}

template<class T>
pair<T>::pair(const T p1, const T p2)
{
        item1 = p1;
        item2 = p2;
}

template<class T>
void pair<T>::first() const
{
        cout << item1 << endl;
}

template<class T>
void pair<T>::second() const
{
        cout << item2 << endl;
}

#ifdef NOAUTO
#pragma define_template pair<int>
#pragma define_template pair<char>
#endif

////////////////////////////////////////////////////////////////////////////////
// prog.cxx
#include <iostream.h>
#include "pair.h"
void main()
{
        pair<int>       int_pair(1,2);
        pair<char>      char_pair('a','b');

        int_pair.first();
        int_pair.second();
        char_pair.first();
        char_pair.second();
}


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

% rm *auto*
% rm -r cxx_repository
% time make prog_noauto
cxx -c -o pair.o -DNOAUTO pair.cxx
cxx -o prog_noauto -nopt -DNOAUTO prog.cxx pair.o
2.43u 0.60s 0:03 93% 5+14k 0+0io 0pf+0w
% time make prog_auto
cxx -o prog_auto -pt prog.cxx
3.54u 1.03s 0:04 93% 5+14k 0+0io 0pf+0w
% prog_auto
1
2
a
b
% prog_noauto
1
2
a
b

================================================================================