This is an archival dump of old wiki content --- see scipy.org for current material

I (DavidCournapeau) will put here some findings/ideas about a system for runtime optimizations in numpy/scipy.

Requirements:
  • Provide interface to pure C functions (that is, the user of the functions available in plugins should not even be aware they are from plugins, except an eventual initialization call)
  • Portable
  • Simple (no COM, etc...)
  • scalable to hundred of functions: Should be mostly automatic from the list of function declaration (in C; what about Fortran ? Can we use f2py for fortran ?) and for each function the list of implementation
Problems:
  • we should wrap the names of all used functions, to avoid name clash (foo in a .so, we always call wrapped_foo). I don't think any other way is possible without losing portability (namespace of symbols in shared code).
  • For a set of functions (say the fft, or blas set), should all implementations have all functions ?
  • What about sets which depend on optional dependencies ?
  • loading a plugin in multi-threaded code: putting a lock around the whole plugin loading is possible ? If yes, easy.
  • The logic to get a plugin location from a set of parameters is not so trivial: for example, blas/lapack have many different possible names depending on the platforms. We could generate the mapping at build time, though, with possible customization for advanced usage ?

Prototype:

I have a really preliminary prototype working. It aims at adressing the following issues:
  • generale usage from plugin user
  • automatic code generation from a list of protoypes (C function declarations).

See here: https://code.launchpad.net/~david-ar/+junk/numplug

Assuming we have the list of functions in a text file, say five functions foo1, ... foo5:

   1 void    foo1();
   2 int     foo2();
   3 int     foo3(int);
   4 int     foo4(double* , double*);
   5 int     foo5(double* , double*, int);

The build system would then takes care of wrapping those functions, generating a header (plugapi.h) which will be used by the consumer (main.c), and a c file which load the functions (plugapi.c):

   1 /*
   2  * main.c
   3  */
   4 #include <stdlib.h>
   5 #include <stdio.h>
   6 
   7 #include "plugapi.h"
   8 
   9 int main()
  10 {
  11         double *a = NULL, *b = NULL;
  12         int n = 0;
  13 
  14         int st;
  15 
  16         /* Change argument to 0 or 1 */
  17         st = init_foo(1);
  18         if (st != 0) {
  19                 fprintf(stderr, "Error loading plug, status is %d\n", st);
  20                 fprintf(stderr, "Exciting...\n");
  21                 exit(EXIT_FAILURE);
  22         }
  23 
  24         npyw_foo1();
  25         npyw_foo2();
  26         npyw_foo3(n);
  27         npyw_foo4(a, b);
  28         npyw_foo5(a, b, n);
  29 
  30         return 0;
  31 }

The templates for the plugapi.h and plugapi.c are:

   1 #ifndef _PLUG_API_H_
   2 #define _PLUG_API_H_
   3 
   4 FILL_DECLS
   5 
   6 int init_foo(int imp);
   7 
   8 #endif
   9 

   1 #include "plugapi.h"
   2 
   3 /*
   4  * At some point, this should be platform independant starting from here
   5  */
   6 int init_foo(int imp)
   7 {
   8         void* hdl;
   9         int st = 0;
  10 
  11         hdl = load_foo(imp);
  12         if (hdl == NULL) {
  13                 return NPYW_FAIL_LOAD_PLUG;
  14         }
  15 
  16         /*
  17          * XXX: it would be good to set all function pointers to dummy
  18          * functions, to make debugging easier ?
  19          */
  20         FILL_WRAPPERS
  21 
  22         return st;
  23 
  24 fail_load_func:
  25         unload_foo(hdl);
  26         return NPYW_FAIL_LOAD_FUNC;
  27 }


ProposedEnhancements

SciPy: RuntimeOptimization (last edited 2015-10-24 17:48:27 by anonymous)