-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Upgrade PRIMA.jl for the future PRIMA v0.8.0 #29
base: main
Are you sure you want to change the base?
Conversation
I do not like the idea of interfacing in Julia the new high level API of the prima C library. It would be cleaner and simpler to update the prototypes of the different algorithms (formerly accessible via I realise that the C interface to the different base algorithms ( |
One alternative is to use a patch based on your PR @emmt when we compile the new release |
This is a very good idea and would be very nice indeed. In the mean time, I have started the conversion of |
Can you push on this branch? I can easily regenerate |
Hi @amontoison and @emmt
The signatures of individual C functions such as In contrast, the signature of the C function int prima_minimize(const prima_algorithm_t algorithm, const prima_problem_t problem, const prima_options_t options, prima_result_t *const result); When we want to expose more arguments of the Fortran subroutines, we will just enrich the fields of This is another reason why Thanks. |
This is the |
If more options are added to the C structure, it means that the code wrappers will have to be updated just as if other arguments are added to the base algorithms with, again, the additional difficulty to deal with a C structure. In practice, this is feasible in Julia, but not all types of C structures can be reliably directly interfaced (believe me, I would have preferred it to be possible, as it would have greatly simplified my life in a number of applications). To solve this technical problem there is another possibility that can satisfy everyone if we can simply manage the C structure by using mutators/accessors. Typically, the C API could provide:
This is commonly used by many C libraries to facilitate bindings with other langages and yet allow for the possibilities offered by the library to be enriched as the code evolves. If these functions deal with simple arguments like integer or floating-point values, pointers to arrays of such values or to opaque structures, then it is easy to write bindings and to keep a similar high level interface. I am confident that such an API can be quickly written on top of the current C API with no or only slight changes. The structure describing the PRIMA problem can be kept public for codes that prefer a direct access. In other words any of the two types of use (accessing directly the structure or considerenig it as opaque and using accessors and mutators) can co-exist. I thank that we can quickly converge to a solution that satisfies everyone's needs and desires and that is maintainable to the long term. I am ready to draft a first version of such a C API. |
I am not sure about this, due to my ignorance about C and Julia. Take the structure prima_options_t options;
prima_init_options(&options);
options.iprint = PRIMA_MSG_EXIT;
options.rhoend = 1e-6;
options.maxfun = 500*n;
options.callback = &callback; Now assume that a new field
I agree with this methodology. See below.
If my understanding is correct, you mean the See also
I am not sure about this one. Is it still needed given
I suppose it is
I am not sure why we would need such a function to get the termination status etc. What would the function do other than reading directly
There is But we do not have See the following examples about the usage of these functions: https://github.com/libprima/prima/blob/main/c/examples/newuoa/newuoa_example.c
I agree with the idea. However, due to my ignorance, I am not sure what "The structure describing the PRIMA problem can be kept public" and "two types of use (accessing directly the structure or considerenig it as opaque and using accessors and mutators) can co-exist" mean. Is it considered abnormal to have both types of use co-exist? Anyway, I suppose we need the help of @nbelakovski here. He developed the current version of the C binding, based on the previous one by @jschueller (many thanks to both!).
I hope so! Thank you very much! |
If the C structures of PRIMA only contains "bit" type like int, float or opaque structure (Ptr{Cvoid}) we can easily interface them in Julia and we don't need additional setter / getter in the C interface. The main issue is when we deal with String (vector of char) or any other vector of int / float. The Julia structure is a "mirror" of the C structure and must be aligned (same number of bits). An example to illustrate the issue is when you want to solve a linear optimization problem: |
|
I think we must invite @nbelakovski to the conversation because he is the one who is more familiar with the current C API. My knowledge of C is very limited. |
That a lot of reactions! I'll try to answer to the most important points to clarify what I am suggesting. First of all, I am not saying that the current C API is wrong. I am just suggested it has to be augmented by a few functions and perhaps modified a bit to fit our needs.
It is almost true except that it should takes pointer of structures as arguments, not structure instances.
This is exactly what I want to avoid (and the problem is not specific to Julia) because it is not always possible/safe to deal with C structures in an another language. This requires to know exactly how the members of the structure are layered, at which memory offsets, etc. and this may depend on the compiler. Even though there maybe there is some standadized ABI, the foreign langage may not offer the flexibility to read/write at a given memory address.
Julia have structures that can be stored in memory more or less like C structures with same alignment and offsets (provided these structures are immutable) but I had issues with some such C structures for which C and Julia use different offsets (it may be due to
Strings are indeed another thing that may pose problem. But there is a clean solution in Julia which is fully supproted by
As I said above, this is doable in Julia but I would rather avoid it.
Yes this is true but it is not the types of the members that is the issue it is how they are stored in the structure. What I propose (once again this is a very common solution) is something like: typedef struct { ... /* members stored in the context */ } prima_context_t;
/* get address of a new instantiated context (considered as an opaque structure in what follows) */
prima_context_t* ctx = prima_context_new(... /* arguments to initialize the context */);
/* set options, and problem constraints with "mutators" */
prima_context_set_bounds(ctx, lo, up);
prima_context_set_opt1(ctx, val1);
prima_context_set_opt2(ctx, val2);
...
/* solve the problem */
prima_context_solve(ctx);
/* retrieve parameters with accessors */
prima_rc_t status = prima_context_get_status(ctx);
double fx = prima_context_get_fval(ctx);
...
/* release context structure and associated ressources */
prima_context_free(ctx); This kind of API can sit on top of the existing C API (which is simpler for a C user) but implementing it may be the opportunity to improve some aspects:
As I proposed, I can quite quickly write this C API (with better function names) in another branch to illustrate what can be done and so that we can discuss on something concrete (as we did about the |
Of course. |
I have done this PR (libprima/prima#189) to serve as an example. |
Thanks for inviting me to the discussion. I have a couple questions. Keep in mind I'm not familiar with Julia.
It's not clear to me what the difficultly is in dealing with C structures in Julia, could you provide a simple example to illustrate this? Keep in mind that PRIMA is meant only for the 5 algorithms already contained within it, new algorithms will not be added, and while certain implementation details may change the algorithms themselves largely (or entirely) will not, so the interface we have now is largely stable, save for adding a few more int/float options here and there.
|
As I said, handling C structures is doable in Julia but has a number of issues:
All these disappear when calling a function that only takes bare numerical values, address of such values, or pointers to arrays of such values. This is used by many C libraries to facilitate bindings in other languages. What I propose in libprima/prima#189 can sit next to the existing API, the two APIs can co-exist. In this PR, the only change to the existing API is to pass structures by address not by value (to save stack space), but this is not mandatory to implement the alternative API. |
@emmt @zaikunzhang
Related issue: #28
I cross-compiled the version
0.8.0
ofPRIMA
and pushed thegenerated
PRIMA_jll.jl
on my fork:https://github.com/amontoison/PRIMA_jll.jl
I used
gen/wrapper.jl
andClang.jl
to regeneratesrc/wrappers.jl
.We have the new Julia wrappers for the updated C interface.
We can now work on
src/PRIMA.jl
.Continuous integration will use my fork of
PRIMA_jll.jl
.I only cross-compiled PRIMA on Linux / Windows / Mac Intel but I will add tarballs for other platforms soon (FreeBSD / Apple ARM).