Skip to content

Commit 05b12cf

Browse files
alexhenrierth
authored andcommitted
PERF Shrink arrays to size in liblinear helper dense_to_sparse (scikit-learn#14026)
1 parent e669a89 commit 05b12cf

File tree

1 file changed

+15
-27
lines changed

1 file changed

+15
-27
lines changed

sklearn/svm/src/liblinear/liblinear_helper.c

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
* expected to be an array of length nrow*ncol.
88
*
99
* Typically the matrix will be dense, so we speed up the routine for
10-
* this case. We create a temporary array temp that collects non-zero
11-
* elements and after we just memcpy that to the proper array.
10+
* this case. We create an array big enough to hold the largest possible
11+
* number of non-zero elements and after collecting them we just call
12+
* realloc to shrink the array and reclaim any unused memory.
1213
*
1314
* Special care must be taken with indices, since libsvm indices start
1415
* at 1 and not at 0.
@@ -20,20 +21,22 @@ static struct feature_node **dense_to_sparse(double *x, npy_intp *dims,
2021
{
2122
struct feature_node **sparse;
2223
int i, j; /* number of nonzero elements in row i */
23-
struct feature_node *temp; /* stack for nonzero elements */
2424
struct feature_node *T; /* pointer to the top of the stack */
2525
int count;
2626

2727
sparse = malloc (dims[0] * sizeof(struct feature_node *));
2828
if (sparse == NULL)
29-
goto sparse_error;
30-
31-
temp = malloc ((dims[1]+2) * sizeof(struct feature_node));
32-
if (temp == NULL)
33-
goto temp_error;
29+
return NULL;
3430

3531
for (i=0; i<dims[0]; ++i) {
36-
T = temp; /* reset stack pointer */
32+
/* allocate stack for nonzero elements */
33+
T = sparse[i] = malloc((dims[1]+2) * sizeof(struct feature_node));
34+
if (T == NULL) {
35+
for (j=0; j<i-1; j++)
36+
free(sparse[j]);
37+
free(sparse);
38+
return NULL;
39+
}
3740

3841
for (j=1; j<=dims[1]; ++j) {
3942
if (*x != 0) {
@@ -55,27 +58,12 @@ static struct feature_node **dense_to_sparse(double *x, npy_intp *dims,
5558
T->index = -1;
5659
++ T;
5760

58-
/* allocate memory and copy collected items*/
59-
count = T - temp;
60-
sparse[i] = malloc(count * sizeof(struct feature_node));
61-
if (sparse[i] == NULL) {
62-
int k;
63-
for (k=0; k<i; k++)
64-
free(sparse[k]);
65-
goto sparse_i_error;
66-
}
67-
memcpy(sparse[i], temp, count * sizeof(struct feature_node));
61+
/* shrink stack to size */
62+
count = T - sparse[i];
63+
sparse[i] = realloc(sparse[i], count * sizeof(struct feature_node));
6864
}
6965

70-
free(temp);
7166
return sparse;
72-
73-
sparse_i_error:
74-
free(temp);
75-
temp_error:
76-
free(sparse);
77-
sparse_error:
78-
return NULL;
7967
}
8068

8169

0 commit comments

Comments
 (0)