This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/TMS320C6748: C6000-CGT 8.3 very slow compilation speed

Part Number: TMS320C6748
Other Parts Discussed in Thread: C6000-CGT

Tool/software: TI C/C++ Compiler

Starting of C6000-CGT 8.3 compiler time of project compilation has dramatically increased up to 5 minutes. There were no optimizations set up. What a reason might cause such delays in the compilation?

  • Is most of the time spent compiling one file?  If so, for that file, please follow the directions in the article How to Submit a Compiler Test Case.

    Thanks and regards,

    -George

  • George Mock said:

    Is most of the time spent compiling one file? 

    I don't think so. It seems it depends mostly of c/c++ compiler (c files're compiled much faster),  templates  usage and c++ compiler warnings. The process of building seems to delay  for more time if it is some warnings during a file compilation occur.

    And the main thing about project compilation speed - it was really much faster using C6000 7.4.23 CGT.

  • Egor Kharitonov said:
    The process of building seems to delay  for more time if it is some warnings during a file compilation occur.

    For one file that sees this delay, please follow the directions in the article How to Submit a Compiler Test Case.  I'll see how long it takes to build this file with versions 7.4.23 and 8.3.x.

    Thanks and regards,

    -George

  • Excluding pieces of code from the project one by one I've found out the bottleneck, that affected building efficacy. The problem seems to be in std:: function, or its initialization, to be more precise.  I created a new project (in an attached zip) and tried to reproduce the problem without unnecessary code. I also measured the time of main.cpp compilation (where the code is placed).

    Here are the results:

     - Just defining a couple of std::function - immediately

    static std::function<void(int)> someCallback;
    static std::function<void(int, int)> someCallback2;
    static std::function<void(float)> someCallback3;
    static std::function<void(short)> someCallback4;
    static std::function<void(char, double)> someCallback5;
    static std::function<void()> someCallback6;
    

    -  Just defining a couple of std::function as members of SomeClass someClass object - immediately;

    class SomeClass{
    public:
    	SomeClass(){
    	}
    	static std::function<void(int)> someCallback;//[CALLBACK_NUM];
    	static std::function<void(int, int)> someCallback2;
    	static std::function<void(float)> someCallback3;
    	static std::function<void(short)> someCallback4;
    	static std::function<void(char, double)> someCallback5;
    	static std::function<void()> someCallback6;
    private:
    	template<typename ...Args>
    	static void emptyHook(Args... args) {
    		asm(" nop");
    	};
    };
    
    SomeClass someObj;

    -  Defining a couple of std::function of similar parameter pack, and initialization each of them by variadic template function emptyHook  ~5 seconds;

    template<typename ...Args>
    static void emptyHook(Args... args) {
    	asm(" nop");
    }
    
    static std::function<void(int)> someCallback;
    static std::function<void(int)> someCallback2;
    static std::function<void(int)> someCallback3;
    static std::function<void(int)> someCallback4;
    static std::function<void(int)> someCallback5;
    static std::function<void(int)> someCallback6;
    
    someCallback  		= emptyHook<int>;
    someCallback2 		= emptyHook<int>;
    someCallback3 		= emptyHook<int>;
    someCallback4 		= emptyHook<int>;
    someCallback5 		= emptyHook<int>;
    someCallback6 		= emptyHook<int>;

    -  Defining a couple of std::function of different parameter pack, and initialization each of them by variadic template function emptyHook  ~27 seconds;

    template<typename ...Args>
    static void emptyHook(Args... args) {
    	asm(" nop");
    }
    
    static std::function<void(int)>          someCallback;
    static std::function<void(int, int)>     someCallback2;
    static std::function<void(float)>        someCallback3;
    static std::function<void(short)>        someCallback4;
    static std::function<void(char, double)> someCallback5;
    static std::function<void()>             someCallback6;
    
    std::function<void(int)> SomeClass::someCallback  	        = emptyHook<int>;
    std::function<void(int, int)> SomeClass::someCallback2 		= emptyHook<int, int>;
    std::function<void(float)> SomeClass::someCallback3 		= emptyHook<float>;
    std::function<void(short)> SomeClass::someCallback4 		= emptyHook<short>;
    std::function<void(char, double)> SomeClass::someCallback5 	= emptyHook<char, double>;
    std::function<void()> SomeClass::someCallback6 			= emptyHook<>;
    
    someCallback  		= emptyHook<int>;
    someCallback2 		= emptyHook<int, int>;
    someCallback3 		= emptyHook<float>;
    someCallback4 		= emptyHook<short>;
    someCallback5 		= emptyHook<char, double>;
    someCallback6 		= emptyHook<>;

    -  Defining a couple of std::function of different parameter pack, and initialization each of them by simple functions, which are analogs of variadic template emptyHook:   ~28 seconds;

    static void someFun(int someValue) {
    	asm(" nop");
    }
    
    static void someFun2(int someValue, int someValue2) {
    	asm(" nop");
    }
    
    static void someFun3(float someValue) {
    	asm(" nop");
    }
    
    static void someFun4(short someValue) {
    	asm(" nop");
    }
    
    static void someFun5(char someValue, double someValue2) {
    	asm(" nop");
    }
    
    static void someFun6() {
    	asm(" nop");
    }
    
    static std::function<void(int)>          someCallback;
    static std::function<void(int, int)>     someCallback2;
    static std::function<void(float)>        someCallback3;
    static std::function<void(short)>        someCallback4;
    static std::function<void(char, double)> someCallback5;
    static std::function<void()>             someCallback6;
    
    someCallback  = someFun;
    someCallback2 = someFun2;
    someCallback3 = someFun3;
    someCallback4 = someFun4;
    someCallback5 = someFun5;
    someCallback6 = someFun6;
    

    -  Calling set variadic template emptyHook with different parameter pack - 2 seconds

    template<typename ...Args>
    static void emptyHook(Args... args) {
    	asm(" nop");
    }
    
    emptyHook(val1);
    emptyHook(val1, val2);
    emptyHook(val1, val2, val3);
    emptyHook(val1, val2, val3, val4);
    emptyHook(val1, val2, val3, val4, val5);
    
    emptyHook(val5, val4, val3, val2, val1);
    emptyHook(val5, val4, val3, val2);
    emptyHook(val5, val4, val3);
    emptyHook(val5, val4);
    emptyHook(val5);
    
    emptyHook(val2);
    emptyHook(val2, val3);
    emptyHook(val2, val3, val4);
    emptyHook(val2, val3, val4, val5);
    emptyHook(val2, val3, val4, val5, val1);

    buildSpeedTest.zip

    What affects compilation time in these constructions? Is there any ones which cause a similar behaviour of the compiler? I attached .pp file in the zip.

    Best regards, Egor.

  • Thank you for submitting a test case.  I reproduced the behavior where one example compiles in about 5 seconds, and the next one compiles in about 27 seconds.  I filed the entry CODEGEN-6452 in the SDOWP system to have this investigated.  You are welcome to follow it with the SDOWP link below in my signature.

    Thanks and regards,

    -George

  • The biggest reason for the compilation time is std::function itself.  If you look at your main.pp, it's close to 20,000 lines, and only about 100 are your code.  std::function brings in a lot of C++ template boilerplate.  If you're just declaring variables, that boilerplate doesn't take any time to discard, but if you're creating a std::function object, then they have to be expanded and instantiated and compiled.  Each different function signature requires its own instantiations, which is why the six assorted functions takes much longer than six of the same function.

    This was not an issue for 7.4.x, because std::function is a C++11 feature that we didn't support until 8.3.x.

    Another issue, specific to C6000, is that there is a "compression" pass that converts some 32-bit instructions into 16-bit instructions.  It contains a cache whose overhead can become significant for large cases, and std::function can make your code into a large case.  You can disable the compression pass with the --no_compress option, which will have no visible effect other than increased code size and reduced compilation time.  You could perhaps do that in Debug mode, if your program still fits, and let the compression happen in Release mode.

    We also have a patch that will speed up the compression pass and reduce your 27-second case by 3-4 seconds.

  • Thank you for investigating, finally, I've decided to use manual implementation of the std::function, something like this:

    namespace alg
    {
    	template <typename R, typename... T>
    	class function
    	{
    	public:
    		function() {
    			_f = emptyFun;
    		}
    
    		function(R(*f)(T...)) {
    			_f = f;
    		}
    
    		R operator()(T... args) {
    			return _f(args...);
    		}
    
    		void operator=(R(*f)(T...)) {
    			_f = f;
    		}
    
    		void bind(R(*f)(T...)) {
    			_f = f;
    		}
    
    		void unbind() {
    			_f = emptyFun;
    		}
    
    	private:
    		R(*_f)(T...);
    
    		static R emptyFun(T... args) {
    			asmNop();
    		}
    
    		static void asmNop() {}
    	};
    }

    I've also tested  --no_compress option, it reduced building time by ~40 s on my PC, but only by ~5 s on my colleague's PC with no essential extension of output binary file. 

    Br,

    Egor.