[Ipopt-tickets] [Ipopt] #234: Bad idea of "std::list<TripletEntry>.sort" in "IpTripletToCSRConverter"

Ipopt coin-trac at coin-or.org
Tue May 13 13:27:22 EDT 2014


#234: Bad idea of "std::list<TripletEntry>.sort" in "IpTripletToCSRConverter"
-------------------------+------------------------
Reporter:  galago        |      Owner:  ipopt-team
    Type:  enhancement   |     Status:  new
Priority:  high          |  Component:  Ipopt
 Version:  3.11          |   Severity:  critical
Keywords:  CSRConverter  |
-------------------------+------------------------
 I am using IPOPT to solve a large scale NLP. When I tried to employ
 PARDISO as my linear solver, its initialization became very slow.
 By Hotspots analysis (shown in the image below), I found that
 “TripletToCSRConverter::InitializeConverter” consumes almost half of my
 optimazation time(30.86 secs of 78.24 secs).
 '''The function “std::list<TripletEntry> entry_list.sort(…)” takes 30 secs
 to finish its job when sorting an array with the length of 860,040.'''
 ----
 I thought “std::list<>.sort” can be replaced by a better implementation.
 Then I commented the original code and wrote a class called MatSorter.

 {{{
         // Create a list with all triplet entries
         //-- std::list<TripletEntry> entry_list(nonzeros);
         //-- std::list<TripletEntry>::iterator list_iterator =
 entry_list.begin();
         //-- for (Index i = 0; i < nonzeros; i++) {
         //--    list_iterator->Set(airn[i], ajcn[i], i);
         //--    list_iterator++;
         //-- }
         //-- DBG_ASSERT(list_iterator == entry_list.end());

         /** Patch #3, 2014-5-6 by Jeffrey Fung, Zhejiang University */
         class MatSorter {               // sort to standard CSC format
                 int *ia, *ja;
         public:
                 MatSorter(int *i, int *j): ia(i), ja(j) {}
                 bool operator () (int i, int j) const {
                         return ia[i] < ia[j] || (ia[i] == ia[j] && ja[i] <
 ja[j]);
                 }
         };

 }}}

 Form the data required and sort an index array “idx_sort[]” which
 functions as “PosTriplet”.

 {{{
 for (k = 0; k < nonzeros; k++) {
                 if (airn[k] > ajcn[k]) {                        // Upper
 triangular of matrix
                         ia_tri[k] = ajcn[k];
                         ja_tri[k] = airn[k];
                 }
                 else {
                         ia_tri[k] = airn[k];
                         ja_tri[k] = ajcn[k];
                 }
                 idx_sort[k] = k;
         }
         // Quick sort algorithm for large arrays
         std::sort(idx_sort, idx_sort + nonzeros, MatSorter(ia_tri,
 ja_tri));

 }}}

 After the modification I performed the same Hotspots analysis. '''Sorting
 time is reduced from 30 secs to 1.14 secs. It was almost of 27X speedup
 for the function “InitializeConverter” and “std::sort()” just consumed
 1.07 secs.'''
 Detailed time summary is shown in the images below.
 I wonder if my experience could contribute to your next build.
 The modified file “IpTripletToCSRConverter.cpp” is also attached.

--
Ticket URL: <https://projects.coin-or.org/Ipopt/ticket/234>
Ipopt <http://projects.coin-or.org/Ipopt>
Interior-point optimizer for nonlinear programs.



More information about the Ipopt-tickets mailing list