KarypisLab / METIS

METIS - Serial Graph Partitioning and Fill-reducing Matrix Ordering
Other
707 stars 139 forks source link

segmentation fault on simple graphs #42

Closed halbux closed 2 years ago

halbux commented 2 years ago

I systematically get a segmentation fault on the default metis version provided by petsc with --download-metis when I partition even simple and not too large graphs ( O(5 millions)). I tried a lot of cases as well as both the 32 and 64 bits version and also increasing ulimit (on Linux). I use Linux and have way enough RAM (32GB) for this example (less than 10% is used here). Here is the shortest possible representative example with that problem (c++). I double checked it and I hope there is no mistake in this example. The below example constructs the containers for a 1D line graph (n vertices connected by edges one by one as in a chain. Both end vertices only have a single neighbor while all other vertices have two neighbors). Either this is something I am doing wrong or there is a bug in at least the metis version used in petsc. I haven't tried on the latest version of this repo and I would love to know if the bug also occurs here or if it was fixed in a recent commit (which one?).

Here is the example producing a segfault. If you don't get a segfault try a 10 millions or more vertices graph.

include "metis.h"

int main(void) { // Number of vertices: int n = 1000000; // Addresses should for example be [0 1 3 5 7 8] for 5 vertices idx_t addresses[n+1]; addresses[0] = 0; addresses[1] = 1; for (int i = 2; i < n; i++) addresses[i] = addresses[i-1] + 2; addresses[n] = addresses[n-1]+1;

// Connected vertices should for example be [1 0 2 1 3 2 4 3] for 5 vertices
idx_t connectivities[2*(n-1)];
connectivities[0] = 1;
for (int i = 1; i < n-1; i++)
{
    connectivities[2*i-1] = i-1;
    connectivities[2*i+0] = i+1;
}
connectivities[2*(n-1)-1] = connectivities[2*(n-1)-2]-1;

idx_t nvtxs = n;
idx_t nEdges = n-1;

idx_t metisOptions[METIS_NOPTIONS];
METIS_SetDefaultOptions(metisOptions);
metisOptions[METIS_OPTION_NUMBERING] = 0; // c numbering (start at 0)

idx_t ncon = 1;
idx_t nParts = 2;
idx_t objval;
idx_t part[nvtxs];

int ret = METIS_PartGraphRecursive ( &nvtxs, &ncon, addresses, connectivities, NULL, NULL, NULL, &nParts, NULL, NULL, metisOptions, &objval, part );

}

halbux commented 2 years ago

well well, I am just too used to these awesome std::vector that I completely forgot that for arrays, the memory has to be allocated (sorry for that). Works just fine! At least if someone is looking for one more simple metis example this code might be useful. Simple fix (ignoring the fact that metis might be using "long unsigned int" for 32 bits) is to use std::vector int vec instead of arrays and providing the arguments to the petsc call with vec.data() (std::vector now guarantees data is contiguous in memory, therefore pointer to first element can be used as argument too)