I haven't done any "professional" profiling, but it seems to me that the 10% are stable, i.e., roughly independent of the size of the permutation.
I just found a much faster alternative: simply bypass MatrixSpace.matrix completely: entries = { (v-1, i): 1 for i, v in enumerate(self) } M = MatrixSpace(ZZ, len(self), sparse = True) return Matrix_integer_sparse(M, entries, False, False) I am not completely sure what's better in the long run... It somehow feels stupid that in order to optimize a function I have to inline it by hand, even if it's only one line. I really miss FriCAS/Aldor. Martin Am Freitag, 15. September 2017 21:31:05 UTC+2 schrieb Maarten Derickx: > > Is it assymptotically 10% or is it 10% for the case in which you are > testing it? In the first case I would be surprised in the second case it is > not that weird. > > See the late_import function in src/sage/rings/complex_field.py for how > you can speed up the import statement for the cyclic import case. > > On Friday, 15 September 2017 20:31:51 UTC+2, Martin R wrote: >> >> I am now trying to speed up Permutation.to_matrix, which is meanwhile one >> of the worst offenders in my application. After some profiling I found the >> following, which is quite a mystery to me. Apparently it is possible that >> importing a module in a method costs a significant amount of time! >> >> QUESTION: is this an oversight or is there a good reason to import >> modules in a relatively fundamental method like MatrixSpace.matrix? >> >> (I checked, moving out the first import makes the whole thing >> (Permutation.to_matrix()) 10% faster. I'm not saying that this is huge, >> but it seems like a significant improvement to me. Unfortunately, the >> second module cannot be easily moved out, because of an import loop) >> >> This is #23870 >> >> Martin >> >> sage: l = [pi for pi in Permutations(8)] >> sage: %lprun -f Permutation.to_matrix -f MatrixSpace.matrix >> [pi.to_matrix() for pi in l] >> Timer unit: 1e-06 s >> >> Total time: 41.8048 s >> File: >> /home/martin/sage-develop/local/lib/python2.7/site-packages/sage/matrix/matrix_space.py >> Function: matrix at line 1354 >> >> Line # Hits Time Per Hit % Time Line Contents >> ============================================================== >> 1354 def matrix(self, >> x=0, coerce=True, copy=True): >> ... >> 1493 362880 2800013 7.7 6.7 if x is None or >> isinstance(x, (int, integer.Integer)) and x == 0: >> 1494 if >> self._copy_zero: # faster to copy than to create a new one. >> 1495 return >> self.zero_matrix().__copy__() >> 1496 else: >> 1497 return >> self.__matrix_class(self, None, False, False) >> 1498 362880 2344112 6.5 5.6 if isinstance(x, >> (int, integer.Integer)) and x == 1: >> 1499 return >> self.identity_matrix().__copy__() >> 1500 362880 1577558 4.3 3.8 m, n, sparse = >> self.__nrows, self.__ncols, self.__is_sparse >> 1501 362880 1462412 4.0 3.5 if >> matrix.is_Matrix(x): >> 1502 if >> x.parent() is self: >> 1503 if >> x.is_immutable(): >> 1504 >> return x >> 1505 else: >> 1506 >> return x.__copy__() >> 1507 else: >> 1508 if >> x.nrows() == m and x.ncols() == n: >> 1509 if >> (x.base_ring() == self.base_ring() >> 1510 >> and x.is_sparse() and not sparse): >> 1511 >> # If x is sparse and large, calling x.dense_matrix() >> 1512 >> # is much faster than calling x.list(). See #20470. >> 1513 >> return x.dense_matrix() >> 1514 x = >> x.list() >> 1515 else: >> 1516 >> raise ValueError("a matrix from %s cannot be converted to " >> 1517 >> "a matrix in %s!" % (x.parent(), self)) >> 1518 362880 5492940 15.1 13.1 from >> sage.groups.matrix_gps.group_element import \ >> 1519 >> is_MatrixGroupElement >> 1520 362880 4978054 13.7 11.9 from >> sage.modular.arithgroup.arithgroup_element import \ >> 1521 >> ArithmeticSubgroupElement >> 1522 362880 2613184 7.2 6.3 if >> is_MatrixGroupElement(x) or isinstance(x, ArithmeticSubgroupElement): >> 1523 return >> self(x.matrix(), copy=False) >> 1524 362880 2036306 5.6 4.9 if isinstance(x, >> (types.GeneratorType,)): >> 1525 x = list(x) >> 1526 362880 1226969 3.4 2.9 if not sparse >> and isinstance(x, dict): >> 1527 x = >> dict_to_list(x, m, n) >> 1528 coerce = True >> 1529 copy = False >> 1530 362880 1354039 3.7 3.2 MC = >> self.__matrix_class >> 1531 362880 2139861 5.9 5.1 if isinstance(x, >> (list, tuple)) and x: >> 1532 if len(x) == >> m: # Try unpacking elements >> 1533 unpacked >> = True >> 1534 new_x = >> [] >> 1535 for v in >> x: >> 1536 l = >> len(new_x) >> 1537 try: >> 1538 >> from sage.structure.element import is_Vector >> 1539 >> if isinstance(v, (list, tuple)) or is_Vector(v): >> 1540 >> # The isinstance check should prevent the "flattening" >> 1541 >> # of v if v is an iterable but not meant to be >> 1542 >> # iterated (e.g., an element of a combinatorial free >> 1543 >> # module). >> 1544 >> new_x.extend(v) >> 1545 >> else: >> 1546 >> raise TypeError >> 1547 >> if len(new_x) - l != n: >> 1548 >> raise TypeError >> 1549 >> except TypeError: >> 1550 >> unpacked = False >> 1551 if >> unpacked: >> 1552 try: >> 1553 >> if sparse: >> 1554 >> return MC(self, list_to_dict(new_x, m, n), >> 1555 >> copy=False, coerce=coerce) >> 1556 >> else: >> 1557 >> return MC(self, new_x, copy=False, coerce=coerce) >> 1558 >> except (TypeError, ValueError): >> 1559 >> pass >> 1560 if len(x) != >> m * n: >> 1561 raise >> TypeError("cannot construct an element of {} from {}!" >> 1562 >> .format(self, x)) >> 1563 if sparse: >> 1564 x = >> list_to_dict(x, m, n) >> 1565 copy = >> False >> 1566 362880 13779340 38.0 33.0 return MC(self, >> x, copy=copy, coerce=coerce) >> >> -- You received this message because you are subscribed to the Google Groups "sage-devel" group. To unsubscribe from this group and stop receiving emails from it, send an email to sage-devel+unsubscr...@googlegroups.com. To post to this group, send email to sage-devel@googlegroups.com. Visit this group at https://groups.google.com/group/sage-devel. For more options, visit https://groups.google.com/d/optout.