[GAP Forum] Stop GAP from storing group properties

Hulpke,Alexander Alexander.Hulpke at colostate.edu
Mon May 10 17:34:17 BST 2021



> On May 8, 2021, at 8:28 PM, Marc Keilberg <keilberg at usc.edu> wrote:
> Now an inflation of 200 bytes or so per group is sufficient for immediate purposes to keep things within my system capabilities

Glad to hear it helped.

> Because before calling Pcgs there is no "Pcgs" component to the group, but afterwards there is.  And this is, apparently, a significantly larger amount of data.  MemoryUsage may report a consumption of about 9k before calling Pcgs, but reports over 157k afterwards.

I’m not entire sure whether `MemoryUsage` really accounts properly for such composite objects (or what is accounted as its memory footprint), in any case to understand what happens one needs to be quite careful with specifying what one does. I frankly cannot imagine where a calculation of the Pcgs would use up/store 150k (unless your group has order p^10000 or so). One could call
TraceMethods(Pcgs);
before calling Pcgs to get information which routine is used.

> Curiously, the memory consumption explosion still happens when creating copies via generators.  


First, while `GeneratorsOfGroup` might be bound to a pcgs, there is no guarantee that it hold the same entries. Use (e.g., as you did) HomePcgs or GeneralizedPcgs .

Next, accessing a stored entry (in particular if not using the arttribute but the bare metal !. operator) cannot cause the calculation/storage of other entries. This could happen through routines that are called on these entries (e.g. GroupByPcgs), in particular by the `View` command that is called to display an object from the command line. In the latter case, it could be avoided by ending an assignment by a double semicolon. (This is a non-issue when calling within a function, as the results of each assignment are not printed).

Best,

  Alexander Hulpke

> 
> 
> This is the output of NamesOfComponent immediately after constructing the groups:
> [ "Size", "OneImmutable", "Order", "GeneratorsOfMagmaWithInverses",
>   "PrimePGroup", "FamilyPcgs", "HomePcgs", "GeneralizedPcgs", "NuclearRank",
>   "MultiplicatorRank", "ANUPQIdentity", "ANUPQAutomorphisms" ]
> 
> Using the function GeneralizedPcgs or simply GeneratorsOfGroup instead of Pcgs, or applying AttributeValueNotSet in conjunction with Pcgs, fixes that problem predictably enough.  
> 
> However, there's still a difference in memory consumption of about 200 bytes. In all variations using functions to get the generators that I've tested the original group always picks up a new component of TrivialSubmagmaWithOne, aka the trivial subgroup, which evidently consumes about 200 bytes.  Indeed, it seems this new component appears even when trying to directly access stored components: using G!.GeneralizedPcgs still computes the trivial subgroup and consumes the same extra 200 bytes or so.
> 
> Now an inflation of 200 bytes or so per group is sufficient for immediate purposes to keep things within my system capabilities, and probably future ones as well (it's all of 10MB extra over some 50k groups).  But is there any way to avoid it?  And any particular reason that even direct access to components is causing more components to be computed and stored?
> 
> Thanks,
> Marc
> 
> 
> On Sat, May 8, 2021 at 1:49 PM Hulpke,Alexander <Alexander.Hulpke at colostate.edu> wrote:
> Dear Forum, Dear Marc Keilberg,
> 
> > I've been looking to sift through a particular family of a few ten-thousand
> > groups, which are not in any of the current libraries, to see if they have
> > certain properties.  While it's relatively easy to construct the entire
> > family of groups via the anupq package, and the test I run on them is
> > relatively quick (a second or two per group on my computer), I run into
> > serious memory consumption issues when I go to start testing them all (with
> > a function specifically written to perform the test in question).  While
> > the list of groups I want only takes up a few gigabytes, and each iteration
> > of the testing function should be consuming a small fraction of that before
> > it completes, my total memory consumption constantly ticks up as I run
> > through the list, ultimately consuming well more memory than the list of
> > groups itself.
> 
> There are tools (such as `AttributeValueNotSet` that aim to do this, but it is still possible that attributes that get called in the course of the calculation still get stored.
> 
> What I have therefore done in such situations is to simply delete the whole group after having used it. This can happen in one of two ways (assuming L is your list of groups):
> 
> a) You do not need the groups, only data obtained from them, or one counterexample:
> 
> for i in [1..Length(L)] do
>   G:=L[i];
>   # now do the test
>   ...
>   Unbind(L[i]);  # so the group is gone as soon as the next iteration assignes G.
> od;
> 
> A more subtle way (with keeping the list) is work on a new group G that is defined the same way (but is a different object. 
> If you have permutation groups, you can do this as:
> 
> G:=Group(GeneratorsOfGroup(L[i]));
> SetSize(G,Size(L[i])); # speeds things up if large
> 
> but I suspect you have PcGroups. For these, it is probably best to make a *new* pc group with the same generators, so that there is nothing stored through attributes of the pcgs. That is, you use:
> 
> G:=GroupByPcgs(Pcgs(L[i]));
> 
> You will get a formally different group with same multiplication rules, and you can discard it once you are done.
> 
> All the best,
> 
>  Alexander Hulpke
> 
> 



More information about the Forum mailing list