[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[minion-cvs] Make FEC wrappers work; add tests and benchmarks.
Update of /home/minion/cvsroot/src/minion/src
In directory moria.mit.edu:/tmp/cvs-serv17806/src
Modified Files:
fec.c
Log Message:
Make FEC wrappers work; add tests and benchmarks.
The new code jumps through some hoops to never allocate more string
than we need - it makes the wrapper code a little hairier, but it
speeds up the runtime by up to a factor of 4.
Index: fec.c
===================================================================
RCS file: /home/minion/cvsroot/src/minion/src/fec.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- fec.c 7 Jul 2003 23:46:51 -0000 1.3
+++ fec.c 8 Jul 2003 18:38:25 -0000 1.4
@@ -649,7 +649,7 @@
sz /= 2 ;
if (index < k)
- memcpy(src[index], fec, sz*sizeof(gf) ) ;
+ memcpy(fec, src[index], sz*sizeof(gf) ) ;
else if (index < code->n) {
p = &(code->enc_matrix[index*k] );
memset(fec, 0, sz*sizeof(gf));
@@ -660,11 +660,8 @@
index, code->n - 1 );
}
-/*
- * shuffle move src packets in their position
- */
static int
-shuffle(gf *pkt[], int index[], int k)
+shuffle(PyObject *pkt[], int index[], int k)
{
int i;
@@ -681,12 +678,14 @@
return 1 ;
}
SWAP(index[i], index[c], int) ;
- SWAP(pkt[i], pkt[c], gf *) ;
+ SWAP(pkt[i], pkt[c], PyObject *) ;
}
}
return 0 ;
}
+
+
/*
* build_decode_matrix constructs the encoding matrix given the
* indexes. The matrix must be already allocated as
@@ -706,7 +705,7 @@
} else
#endif
if (index[i] < code->n )
- memcpy( &(code->enc_matrix[index[i]*k]), p, k*sizeof(gf) );
+ memcpy(p, &(code->enc_matrix[index[i]*k]), k*sizeof(gf) );
else {
fprintf(stderr, "decode: invalid index %d (max %d)\n",
index[i], code->n - 1 );
@@ -742,8 +741,11 @@
if (GF_BITS > 8)
sz /= 2 ;
+#if 0
+ /* Unnecessary now, but harmless -NM */
if (shuffle(pkt, index, k)) /* error if true */
return 1 ;
+#endif
m_dec = build_decode_matrix(code, pkt, index);
if (m_dec == NULL)
@@ -765,7 +767,7 @@
*/
for (row = 0 ; row < k ; row++ ) {
if (index[row] >= k) {
- memcpy(new_pkt[row], pkt[row], sz*sizeof(gf));
+ memcpy(pkt[row], new_pkt[row], sz*sizeof(gf));
free(new_pkt[row]);
}
}
@@ -959,11 +961,13 @@
PyObject *blocks;
int tmp;
+ char *s;
int sz = -1;
- int i;
+ int i, j;
PyObject *o;
PyObject *tup = NULL;
+ PyObject **objPtrs = NULL;
char **stringPtrs = NULL;
int *indices = NULL;
PyObject *result = NULL;
@@ -993,35 +997,67 @@
if (!(tup = PySequence_Tuple(blocks))) {
return NULL;
}
- if (!(stringPtrs = malloc((sizeof(gf*))*fec->k))) {
+ if (!(stringPtrs = malloc(sizeof(gf*)*fec->k))) {
PyErr_NoMemory();
goto err;
- }
- if (!(indices = malloc((sizeof(int))*fec->k))) {
+ }
+ if (!(indices = malloc(sizeof(int)*fec->k))) {
+ PyErr_NoMemory();
+ goto err;
+ }
+ if (!(objPtrs = malloc(sizeof(PyObject*)*fec->k))) {
PyErr_NoMemory();
goto err;
}
for (i = 0; i < fec->k; ++i) {
o = PyTuple_GET_ITEM(tup, i);
- if (!PyArg_ParseTuple(o, "is#", &indices[i], &stringPtrs[i],
- &tmp)) {
+ if (!PyArg_ParseTuple(o, "is#", &j, &s, &tmp)) {
PyErr_SetString(mm_FECError,
"decode expects a list of index-string tuples");
goto err;
}
- if (sz<0)
+ if (sz<0) {
sz = tmp;
- else if (sz != tmp) {
+ } else if (sz != tmp) {
PyErr_SetString(mm_FECError,
"decode expects equally long strings");
goto err;
}
+ indices[i] = j;
+ objPtrs[i] = PyTuple_GET_ITEM(o, 1);
}
-
- if (!(result = PyString_FromStringAndSize(NULL, sz*fec->k))) {
+ if (shuffle(objPtrs, indices, fec->k))
+ goto err;
+ if (!(result = PyList_New(fec->k))) {
PyErr_NoMemory(); goto err;
}
-
+
+ /* Now set up the result for the user, and stringPtrs/indices
+ * for fec_decode. Any string objects that are in the right
+ * place in objPtrs won't have their underlying string buffers
+ * touched: we just incref those objects and use them in the
+ * result. Any other strings, however, will have their
+ * contents zapped by fec_decode: we need to copy those to
+ * keep Python strings nice and immutable.
+ *
+ * This way, we never allocate more memory than we need.
+ *
+ */
+ for (i = 0; i < fec->k; ++i) {
+ o = objPtrs[i];
+ if (indices[i] < fec->k) {
+ assert(indices[i] == i);
+ Py_INCREF(o);
+ PyList_SET_ITEM(result, i, o);
+ stringPtrs[i] = PyString_AS_STRING(o);
+ } else {
+ o = PyString_FromStringAndSize(NULL, sz);
+ memcpy(PyString_AS_STRING(o),
+ PyString_AS_STRING(objPtrs[i]), sz);
+ PyList_SET_ITEM(result, i, o);
+ stringPtrs[i] = PyString_AS_STRING(o);
+ }
+ }
Py_BEGIN_ALLOW_THREADS
tmp = fec_decode(fec, (gf**) stringPtrs, (int*) indices, sz);
Py_END_ALLOW_THREADS
@@ -1029,13 +1065,9 @@
if (tmp)
goto err;
- for (i = 0; i < fec->k; ++i) {
- memcpy(PyString_AsString(result)+sz*i, stringPtrs[i], sz);
- free(stringPtrs[i]);
- }
-
free(stringPtrs);
free(indices);
+ free(objPtrs);
Py_DECREF(tup);
return result;
@@ -1044,11 +1076,17 @@
Py_DECREF(tup);
if (indices)
free(indices);
- if (stringPtrs)
+ if (objPtrs)
+ free(objPtrs);
+ if (stringPtrs) {
free(stringPtrs);
+ }
+ if (result)
+ Py_DECREF(result);
return NULL;
}
+
static PyMethodDef mm_FEC_methods[] = {
METHOD(mm_FEC, getParameters),