Closed jschueller closed 1 year ago
ok, I applied all remarks, except for the array types, this is needed for C interoperability (actually it works too with gfortran but not ifort)
also we do need the _loc variables to avoid compiler error on the conversion since C types and Fortran types may differ
I've added comments for these issues
I understand and agree with what you said about the _loc variables. I will check other points. Thank you.
except for the array types, this is needed for C interoperability (actually it works too with gfortran but not ifort)
@jschueller I remember you mentioned this issue before. What about other compilers? Isn't it a bug of ifort (I would not be surprised)? Would you mind creating a minimal working example and asking a question on Fortran Discourse and Intel Community? With you example, I can also try other compilers, e.g., nagfor, nvfortran, ... I constantly test PRIMA on ten compilers and make sure that they are all happy.
Explicit-shape arrays are not ideal. It is worthwhile looking a bit deeper into this issue. Thank you.
Type conversion should be explicit, or many compilers will complain.
For example,
x_loc = real(x, kind(x_loc))
...
x = real(x_loc, kind(x))
or
x_loc = real(x, RP)
...
x = real(x_loc, C_DOUBLE)
it's not a compiler bug, assumed-shape array are not compatible because the compiler passes a descriptor instead of the address of the data, it's a known fact, but information is scarce: https://community.intel.com/t5/Intel-Fortran-Compiler/C-interoperability-with-assumed-size-arrays/td-p/1252532
@zaikunzhang do you think the C interface is ok for you ? I was thinking maybe it could be merged. The Python part probably still needs discussion though, that's why I removed it for now, but I can still propose it in a later PR if needed, waiting for a pure Python implementation (#37). 0001-Add-Python-binding.txt
Sorry for the delayed reply.
I have been working on some revisions to lincoa and cobyla, which are motivated by your interface. The revisions would imply changes to the interfaces.
In short, lincoa and cobyla will support more types of constraints natively. See
https://github.com/libprima/prima/blob/dev_cobyla/fortran/lincoa/lincoa.f90 https://github.com/libprima/prima/blob/dev_cobyla/fortran/cobyla/cobyla.f90
for details. Sorry but this takes a lot of time to code.
Hi Zaikun, This is awesome, thanks a lot. There is a side effect of handling bounds, the initial DOE may go above the upper bounds. In the Nlopt version they fixed it by doikg a negative step when needed and the DOE is performed with a step rhobeg*(upperbound-lowerbound) because variables may have very different scales. How did you handle these issues?
"allows to avoids" should be "allow to avoid".
Hi @FrancoisGallard
Currently, lincoa and cobyla accept bound constraints but do not respect them. Users do not need to write their own wrappers to translate bound constraints into linear/nonlinear constraints. Internally, however, bounds are handled in the same way as other linear/nonlinear constraints and hence can be violated.
In future versions (it needs time), the bounds will be respected. I will use the approach already introduced by Powell in BOBYQA. It either moves the starting point or shrinks rhobeg
to make sure that the initial interpolation set stays within the bounds.
Scaling the variables is a related but different topic. It is nontrivial to code the scaling on the Fortran side due to the lack of lambda functions. It should be regarded as a preprocessing procedure that should be conducted by MATLAB/Python/R/Julia interfaces, as has been done in PDFO. In other words, we assume that the problem is well-scaled before being passed to the Fortran code from MATLAB/Python/R/Julia. I do not think this is an unreasonable requirement, because the scaling is much easier to implement in the latter languages.
The MATLAB interface of PRIMA does the scaling if the user requests so by setting scale = true
in the options. To have the same in the Python interface, we may do so by inheriting the interface of PDFO, which is well coded (by @ragonneau Tom).
Thanks.
Zaikun
"allows to avoids" should be "allow to avoid".
ok
Hi @jschueller ,
A new release has been made. It enables lincoa and cobyla to support more types of constraints natively. The signatures of lincoa.f90
and cobyla.f90
are adapted accordingly. It would be great if you could incorporate the changes.
I do not foresee any other significant changes to the signatures of the principle Fortran subroutines (cobyla.f90
, uobyqa.f90
, newuoa.f90
, bobyqa.f90
, lincoa.f90
) in the near future, if ever. That said, further updates to the Fortran implementation will unlikely affect the C/Python interface.
Many thanks for your efforts.
Best regards, Zaikun
https://github.com/jschueller/prima/blob/cport/c/cobyla_c.f90 https://github.com/jschueller/prima/blob/cport/c/lincoa_c.f90
cstrv
as well. nlconstr
(constr
in v0.5.1) must be outputted. I suggest modifying these lines as follows.
! Local variables
integer(IK) :: info_loc
integer(IK) :: iprint_loc
integer(IK) :: maxfun_loc
integer(IK) :: nf_loc
real(RP) :: f_loc
real(RP) :: rhobeg_loc
real(RP) :: rhoend_loc
real(RP) :: x_loc(n)
real(RP) :: xl_loc(n)
real(RP) :: xu_loc(n)
! Read the inputs and convert them to the Fortran side types
x_loc = real(x, kind(x_loc))
xl_loc = real(xl, kind(xl_loc))
xu_loc = real(xu, kind(xu_loc))
rhobeg_loc = real(rhobeg, kind(rhobeg))
rhoend_loc = real(rhoend, kind(rhoend))
maxfun_loc = int(maxfun, kind(maxfun_loc))
iprint_loc = int(iprint, kind(iprint_loc))
! Call the Fortran code
call bobyqa(calfun, x_loc, f_loc, xl=xl_loc, xu=xu_loc, nf=nf_loc, rhobeg=rhobeg_loc, rhoend=rhoend_loc, &
& maxfun=maxfun_loc, iprint=iprint_loc, info=info_loc)
! Write the outputs
x = real(x_loc, kind(x))
f = real(f_loc, kind(f))
nf = int(nf_loc, kind(nf))
info = int(info_loc, kind(info))
Note the following.
&
at the beginning. cobyla.f90
etc. Thanks.
Ok, I updated to master, with the new interface.
Thank you @jschueller for the quick response.
Some quick comments on https://github.com/jschueller/prima/blob/cport/c/lincoa_c.f90 https://github.com/jschueller/prima/blob/cport/c/cobyla_c.f90 Some of them are applicable to other files.
cobyla_c
does not accept linear constraints? The very reason for my last month's work is to enable cobyla to accept such constraints. Without doing so, the user would have to wrap linear constraints as a "black-box nonlinear constraint", which is tedious and error-prone; in addition, it hurts the performance, because such a wrapped constraint hides the linear structure of the problem. Also, lincoa_c
is not accepting linear equality constraints. See the signatures of scipy.optimize.minimize.cobyla
, pdfo.cobyla
, and pdfo.lincoa
for your reference.nlconstr
should be an output of cobyla. ! Local variables
integer(IK) :: info_loc
integer(IK) :: iprint_loc
integer(IK) :: m_loc
integer(IK) :: maxfun_loc
integer(IK) :: nf_loc
real(RP) :: cstrv_loc
real(RP) :: f_loc
real(RP) :: rhobeg_loc
real(RP) :: rhoend_loc
real(RP) :: x_loc(n)
real(RP) :: xl_loc(n)
real(RP) :: xu_loc(n)
ok I've done the cosmetic changes (3 & 4)
but (1) I dont know if we want to expose linear constraints for the sake of simplicity for the same idea I dont think nlconstr is necessary since I already added cstrv (2)
ok I've done the cosmetic changes (3 & 4)
but (1) I dont know if we want to expose linear constraints for the sake of simplicity for the same idea I dont think nlconstr is necessary since I already added cstrv (2)
OK. I may have to give some comments from the viewpoint of numerical optimization algorithms (beyond coding). Most of them have been mentioned above, but it might be better to reiterate and clarify them.
If linear constraints are not exposed, then they will have to be passed as "black-box nonlinear constraints". The obvious disadvantages are as follows.
1.1. It hurts the performance, because the algorithms will not be able to explore the linear structure.
1.2. The users will have to wrap the linear constraints into "black-box nonlinear constraints". This is tedious and error-prone.
Why is it a must to return the value of the nonlinear constraint?
Powell's algorithms are designed for derivative-free optimization problems. Objective/constraint functions of such problems are generally expensive to evaluate --- it is not uncommon that a single function evaluation takes minutes or hours (sometimes days or even more). In addition to the constraint violation cstrv
, it is natural that the user also wants to know the value of the nonlinear constraint at the solution. If we do not return this value, then the user would have to perform an expensive function evaluation (minutes, hours, days, or more) to calculate it, which is an obvious waste because this value was already evaluated.
I believe that François @FrancoisGallard will agree with these two points. He is a practitioner that uses these algorithms in real projects. Maybe François could give some comments.
Thanks.
Hi @jschueller ,
It would be great to write some tests.
cd fortran/cobyla && bash ./mlint -g
I am very bad at Makefiles and bash. What I do is probably clumsy, but it works.
See https://github.com/orgs/libprima/discussions/39 for more comments on tests. I do not mean that these tests should be implemented right now, but we need to have them gradually implemented to some extent. They are all done for the MATLAB interface.
Thanks.
I understand its best to explicit linear constraints, lets keep things simple for now because I think its safe to assume most usages will involve implicit constraints.
for 1. I only tested gcc and the intel compilers, I can try to extend it to the other compilers for 2. I have already CI tests running that verify the interface works
I understand its best to explicit linear constraints, lets keep things simple for now because I think its safe to assume most usages will involve implicit constraints.
Thank you. However, I don't think it will complicate the interface a lot to accept linear constraints in COBYLA and linear equality constraints in LINCOA, whereas the benefits are essential.
For COBYLA, returning the nonlinear constraint value is a must, and it is trivial.
for 1. I only tested gcc and the intel compilers, I can try to extend it to the other compilers
Great!
for 2. I have already CI tests running that verify the interface works
Excellent!
- is out of scope of this PR, and anyway I dont see the point since it will give the same results as the pure fortran layer
This is a complement of 2. If the problems tested in 2 are sufficiently diversified, then 3 may be skipped for the moment.
The diversity of tests in 2 is sufficient if we test at least tens of problems with different sizes, types, features, and difficulties, and they are better randomised. If we test only one or two problems, we will not be sure whether the interface always works correctly or we are just lucky.
Thank you very much for your efforts and consideration.
See the :open_file_folder: files view, the :scroll:action log or :angel: SARIF report for details.
cfun FUNPTR hexval PROCPOINTER
See the :open_file_folder: files view, the :scroll:action log or :angel: SARIF report for details.
cfun FUNPTR hexval PROCPOINTER
See the :open_file_folder: files view, the :scroll:action log or :angel: SARIF report for details.
cfun FUNPTR PROCPOINTER
Hi @jschueller,
I understand that you are still debugging, so cintrf.f90
is not in its final form. Here is a version I suggest when you finalize it.
module cintrf_mod
!--------------------------------------------------------------------------------------------------!
! cintrf_mod provides interoperability with C objective functions
!
! Dedicated to the late Professor M. J. D. Powell FRS (1936--2015).
!--------------------------------------------------------------------------------------------------!
implicit none
private
public :: COBJ, COBJCON, evalcobj, evalcobjcon
abstract interface
subroutine COBJ(x, f) bind(c)
use, intrinsic :: iso_c_binding, only : C_DOUBLE
implicit none
! We cannot use assumed-shape arrays for C interoperability
real(C_DOUBLE), intent(in) :: x(*)
real(C_DOUBLE), intent(out) :: f
end subroutine COBJ
subroutine COBJCON(x, f, constr) bind(c)
use, intrinsic :: iso_c_binding, only : C_DOUBLE
implicit none
! We cannot use assumed-shape arrays for C interoperability
real(C_DOUBLE), intent(in) :: x(*)
real(C_DOUBLE), intent(out) :: f
real(C_DOUBLE), intent(out) :: constr(*)
end subroutine COBJCON
end interface
contains
subroutine evalcobj(cobj_ptr, x, f)
use, non_intrinsic :: consts_mod, only : RP
use, intrinsic :: iso_c_binding, only : C_DOUBLE, C_FUNPTR, C_F_PROCPOINTER
implicit none
type(C_FUNPTR), intent(in), value :: cobj_ptr
real(RP), intent(in) :: x(:)
real(RP), intent(out) :: f
! Local variables
procedure(COBJ), pointer :: obj_ptr
real(C_DOUBLE) :: f_loc
real(C_DOUBLE) :: x_loc(size(x))
! Read the inputs and convert them to the types specified in COBJ
x_loc = real(x, kind(x_loc))
call C_F_PROCPOINTER(cobj_ptr, obj_ptr)
! Call the C objective function
call obj_ptr(x_loc, f_loc)
! Write the output
f = real(f_loc, kind(f))
end subroutine evalcobj
subroutine evalcobjcon(cobjcon_ptr, x, f, constr)
use, non_intrinsic :: consts_mod, only : RP
use, intrinsic :: iso_c_binding, only : C_DOUBLE, C_FUNPTR, C_F_PROCPOINTER
implicit none
type(C_FUNPTR), intent(in), value :: cobjcon_ptr
real(RP), intent(in) :: x(:)
real(RP), intent(out) :: f
real(RP), intent(out) :: constr(:)
! Local variables
procedure(COBJCON), pointer :: objcon_ptr
real(C_DOUBLE) :: constr_loc(size(constr))
real(C_DOUBLE) :: f_loc
real(C_DOUBLE) :: x_loc(size(x))
! Read the inputs and convert them to the types specified in COBJCON
x_loc = real(x, kind(x_loc))
call C_F_PROCPOINTER(cobjcon_ptr, objcon_ptr)
call objcon_ptr(x_loc, f_loc, constr_loc)
! Write the outputs
f = real(f_loc, kind(f))
constr = real(constr_loc, kind(constr))
end subroutine evalcobjcon
N.B.:
obj_ptr
and objcon_ptr
seem more expressive and more consistent with COBJ
and COBJCON
.
Initialization of f
/f_loc
and constr
/constr_loc
is not needed.
I understand that the +10
in the size of constr_loc
is for debugging, and I am sure that you will not include it in the final version. This kind of code would hide bugs. It is better to make the code crash when there is a bug rather than covering it.
I ordered the local variables alphabetically.
Many thanks for your efforts and consideration.
Zaikun
https://github.com/jschueller/prima/actions/runs/5771947549/workflow#L41-L46
Compilers supported by the Fortran implementation of PRIMA are gfrotran, ifort, ifx, nagfor, nvfortran, Classic Flang, AOCC Flang, Arm Flang. The latest versions of these compilers are constantly tested using GitHub actions. Absoft af95, Oracle sunf95, and g95 are not supported, because they are discontinued without sufficient support for Fortran 2008 constructs.
For tests and verification, -Wall
is not sufficient for gfortran. -Wextra
(and even Werror
) should be included as well. Warnings should not be tolerated except for those due to compiler bugs. Below are the compiler options I use for tests and debugging. See https://github.com/libprima/prima/blob/main/fortran/tests/makefiles/Makefile.common for more detail.
-pedantic -Weverything -Wall -Wextra -Minform=warn -Mstandard -Mbounds -Mrecursive
-pedantic -Weverything -Wall -Wextra -Minform=warn -Mstandard -Mbounds -Mrecursive -Mchkptr
-Wall -Wextra -Wpedantic -pedantic -fimplicit-none -frecursive -fcheck=all -fstack-check
-warn all -debug extended -fimplicit-none -standard-semantics -assume recursion
-u -C -C=alias -C=dangling -C=intovf -C=undefined -kind=unique -Warn=constant_coindexing -Warn=subnormal
-C -Wall -Wextra -Minform=warn -Mstandard -Mrecursive -Mbounds -Mchkstk -Mchkptr -Mchkstk
-pedantic -Weverything -Wall -Wextra -Minform=warn -Mstandard -Mrecursive -Mbounds -Mchkptr
Up to v0.6, the Fortran implementation of COBYLA does not work with AOCC 4.0 Flang. I believe it is a bug of the compiler. I note that AOCC 4.1 is released yesterday. ~To be tested.~ The problem remains.
Thanks.
Hi @jschueller ,
It would be great to write some tests.
- Some linting scripts that compile the interfaces with as many compilers as possible, making sure that everything works without a warning. For your reference, here is what I do for the MATLAB interfaces: https://github.com/libprima/prima/blob/main/matlab/mex_gateways/tests/makefiles/Makefile.common https://github.com/libprima/prima/blob/main/fortran/common/mlint You may try
cd fortran/cobyla && bash ./mlint -g
I am very bad at Makefiles and bash. What I do is probably clumsy, but it works. 2. Some tests to verify that interfaces work correctly. 3. Some tests to benchmark the solvers against other standard libraries, e.g., PDFO and NLopt, which provide Powell's methods based on the Fortran 77 implementation.
See https://github.com/orgs/libprima/discussions/39 for more comments on tests. I do not mean that these tests should be implemented right now, but we need to have them gradually implemented to some extent. They are all done for the MATLAB interface.
Thanks.
@jschueller and anyone interested in the development of PRIMA, make sure to read
https://github.com/orgs/libprima/discussions/39
My experiences in past years teach me three things.
https://github.com/jschueller/prima/blob/cport/c/prima.c
I suggest renaming prima_function_con
to prima_objcon
and prima_function
to prima_obj
, to be consistent with https://github.com/jschueller/prima/blob/cport/c/cintrf.f90.
In addition, function_con
does not work so well by itself:
function_constraint
or fun_con
is more reasonable in terms of abbreviations;function
and constraint
side by side, as they are quite different things; the counterpart of "constraint" is "objective", not "function";https://github.com/jschueller/prima/blob/cport/c/prima.c
The function passed to cobyla is called calcfc
rather than calfun
.
Sorry for my ignorance about CMake. Where is the place to specify compiler options? The following options must be applied so that the local arrays and automatic arrays will be allocated on the heap, rather than on the stack. Otherwise, stack overflow may occur if the problem is sufficiently large.
-fno-stack-arrays
-heap-arrays
-Mnostack_arrays
-fno-stack-arrays
N.B.: In the context of derivative-free optimization, the computational cost is dominated by function evaluations (i.e., calfun
or calcfc
), a single of which can take minutes, hours, days, or even months. Therefore, it makes no sense to worry about the performance difference between stack and heap in the implementation of the solvers.
See the :open_file_folder: files view, the :scroll:action log or :angel: SARIF report for details.
cfun cobj NVHPC objcon
See the :open_file_folder: files view, the :scroll:action log or :angel: SARIF report for details.
cmflags
See the :open_file_folder: files view, the :scroll:action log or :angel: SARIF report for details.
cmflags
ok thanks for the compiler flags, but I didnt succeed with aflang:
[ 1%] Building Fortran object fortran/CMakeFiles/primaf.dir/common/consts.F90.o
F90-F-0004-Unable to open MODULE file iso_fortran_env.mod (/home/runner/work/prima/prima/fortran/common/consts.F90: 63)
F90/x86-64 Linux Flang - 1.5 2017-05-01: compilation aborted
isnt iso_fortran_env a standard module of fortran ?
Hi @jschueller ,
iso_fortran_env
is standard, but aflang cannot find it for some reason starting from AOCC 4.1, unless aflang is located in the default bin directory of AOCC. If the new script still does not work, tell me. Thanks.
Zaikun
hello @zaikunzhang
hello @zaikunzhang
thanks; now it builds but the cobyla & lincoa fortran examples crash or assert (not using the C layer)
ok I synced to master
Thank you @jschueller . Could you direct me to the failure log? I will check it.
Thank you.
yes; see https://github.com/jschueller/prima/actions/runs/5801361977/job/15725463847
here I run the fortran/examples as tests for the pure fortran side:
1: Test command: /home/runner/work/prima/prima/fortran/t_primaf_cobyla
1: Working Directory: /home/runner/work/prima/prima/fortran
1: Test timeout computed to be: 10000000
1/10 Test #1: cobyla_f .........................***Exception: SegFault 0.11 sec
...
: Test command: /home/runner/work/prima/prima/fortran/t_primaf_lincoa
5: Working Directory: /home/runner/work/prima/prima/fortran
5: Test timeout computed to be: 10000000
5: 0: Subscript out of range for array x (/home/runner/work/prima/prima/fortran/common/linalg.f90: 665)
5: subscript=6, lower bound=1, upper bound=5, dimension=1
5/10 Test #5: lincoa_f .........................***Failed 0.01 sec
0: Subscript out of range for array x (/home/runner/work/prima/prima/fortran/common/linalg.f90: 665)
subscript=6, lower bound=1, upper bound=5, dimension=1
...
The following tests FAILED:
Errors while running CTest
1 - cobyla_f (SEGFAULT)
5 - lincoa_f (Failed)
yes; see https://github.com/jschueller/prima/actions/runs/5801361977/job/15725463847
here I run the fortran/examples as tests for the pure fortran side:
1: Test command: /home/runner/work/prima/prima/fortran/t_primaf_cobyla 1: Working Directory: /home/runner/work/prima/prima/fortran 1: Test timeout computed to be: 10000000 1/10 Test #1: cobyla_f .........................***Exception: SegFault 0.11 sec ... : Test command: /home/runner/work/prima/prima/fortran/t_primaf_lincoa 5: Working Directory: /home/runner/work/prima/prima/fortran 5: Test timeout computed to be: 10000000 5: 0: Subscript out of range for array x (/home/runner/work/prima/prima/fortran/common/linalg.f90: 665) 5: subscript=6, lower bound=1, upper bound=5, dimension=1 5/10 Test #5: lincoa_f .........................***Failed 0.01 sec 0: Subscript out of range for array x (/home/runner/work/prima/prima/fortran/common/linalg.f90: 665) subscript=6, lower bound=1, upper bound=5, dimension=1 ... The following tests FAILED: Errors while running CTest 1 - cobyla_f (SEGFAULT) 5 - lincoa_f (Failed)
This particular error is due to a known bug of aocc flang:
https://github.com/flang-compiler/flang/issues/1238
In short, the Fortran standard specifies that x(m:n) is an empty array when m>n, even if m is lager than the upper bound of the index. Aocc flang does not handle this correctly.
To circumvent this problem, you may remove "-Mbounds" from the options of aocc flang. This is not ideal, but we have no other solution before AMD fixed the bug.
Any other error on the Fortran side?
https://github.com/jschueller/prima/blob/cport/c/cintrf.f90
Hi @jschueller ,
May I ask what is the reason for packing f
and constr
together as fcon
?
To me, this choice has the style of Powell's original Fortran 77 code, and it is exactly what PRIMA strives to avoid. I believe that each variable should have one and only one purpose, and different objects should not be packed together.
If we choose to use one variable to represent f
and constr
together, then this is the flow of the data:
f
and constr
f
and constr
as fcon
fcon
fcon
into f
and constr
f
and constr
f
and constr
as fcon
and return itfcon
fcon
as f
and constr
I am not sure what is the advantage of this flow compared with transferring f
and constr
separately.
If we had many (say 5) objects like f
and constr
to be evaluated together, then I would agree that it might be better to pack them into a structure. But it seems not the case here.
Thank you.
thanks, removing -Mbounds took care of the lincoa assert on the fortran side there is another problem: the cobyla example segfaults with aocc:
Program received signal SIGSEGV, Segmentation fault.
0x0000555555555d10 in calcfc_mod::calcfc_chebyquad (f=<error reading variable: Cannot access memory at address 0x0>, x=<error reading variable: Location address is not set.>, constr=...) at /home/runner/work/prima/prima/fortran/examples/cobyla/cobyla_example.f90:22
22 subroutine calcfc_chebyquad(x, f, constr)
#0 0x0000555555555d10 in calcfc_mod::calcfc_chebyquad (f=<error reading variable: Cannot access memory at address 0x0>, x=<error reading variable: Location address is not set.>, constr=...) at /home/runner/work/prima/prima/fortran/examples/cobyla/cobyla_example.f90:22
#1 0x00007ffff7f126e9 in calcfc_internal (f_internal=<error reading variable: Cannot access memory at address 0x0>, x_internal=<error reading variable: Location address is not set.>, constr_internal=...) at /home/runner/work/prima/prima/fortran/cobyla/cobylb.f90:667
#2 0x00007ffff7ed8891 in evaluate_mod::evaluatefc (calcfc=0x4155415641574155, f=0.04642817229746083, x=..., constr=...) at /home/runner/work/prima/prima/fortran/common/evaluate.f90:191
#3 0x00007ffff7f1b1b7 in initialize_cobyla_mod::initxfc (calcfc=<optimized out>, iprint=<optimized out>, maxfun=<optimized out>, ctol=<optimized out>, f0=<optimized out>, ftarget=<optimized out>, rhobeg=<optimized out>, nf=<optimized out>, info=<optimized out>, constr0=..., x0=..., chist=..., conhist=..., conmat=..., cval=..., fhist=..., fval=..., sim=..., simi=..., xhist=..., evaluated=...) at /home/runner/work/prima/prima/fortran/cobyla/initialize.f90:156
#4 0x00007ffff7f0e708 in cobylb_mod::cobylb (calcfc=<optimized out>, iprint=<optimized out>, maxfilt=<optimized out>, maxfun=<optimized out>, ctol=<optimized out>, cweight=<optimized out>, eta1=<optimized out>, eta2=<optimized out>, ftarget=<optimized out>, gamma1=<optimized out>, gamma2=<optimized out>, rhobeg=<optimized out>, rhoend=<optimized out>, f=<optimized out>, nf=<optimized out>, cstrv=<optimized out>, info=<optimized out>, amat=..., bvec=..., constr=..., x=..., chist=..., conhist=..., fhist=..., xhist=...) at /home/runner/work/prima/prima/fortran/cobyla/cobylb.f90:213
#5 0x00007ffff7f09224 in cobyla_mod::cobyla (calcfc=1096237397, m_nlcon=0, f=0.04642817229746083, cstrv=0, f0=0, nf=0, rhobeg=0, rhoend=0, ftarget=0, ctol=0, cweight=0, maxfun=0, iprint=0, eta1=0, eta2=0, gamma1=0, gamma2=0, maxhist=0, maxfilt=0, info=0, x=<error reading variable: value requires 750599937872512 bytes, which is more than max-value-size>, nlconstr=<error reading variable: Cannot access memory at address 0x0>, aineq=<error reading variable: value requires 6262704000 bytes, which is more than max-value-size>, bineq=..., aeq=<error reading variable: value requires 710976 bytes, which is more than max-value-size>, beq=..., xl=<error reading variable: value requires 17518252251111699504 bytes, which is more than max-value-size>, xu=..., nlconstr0=<error reading variable: value requires 6262704000 bytes, which is more than max-value-size>, xhist=<not allocated>, fhist=<not allocated>, chist=<not allocated>, nlchist=<not allocated>) at /home/runner/work/prima/prima/fortran/cobyla/cobyla.f90:600
#6 0x00005555555568ea in cobyla_exmp () at /home/runner/work/prima/prima/fortran/examples/cobyla/cobyla_example.f90:106
full log: https://github.com/jschueller/prima/actions/runs/5807492241/job/15742432101
as for the argument packing, that was just to try if it can avoid another cobyla segfault on the C side
thanks, removing -Mbounds took care of the lincoa assert on the fortran side there is another problem: the cobyla example segfaults with aocc:
Program received signal SIGSEGV, Segmentation fault. 0x0000555555555d10 in calcfc_mod::calcfc_chebyquad (f=<error reading variable: Cannot access memory at address 0x0>, x=<error reading variable: Location address is not set.>, constr=...) at /home/runner/work/prima/prima/fortran/examples/cobyla/cobyla_example.f90:22 22 subroutine calcfc_chebyquad(x, f, constr) #0 0x0000555555555d10 in calcfc_mod::calcfc_chebyquad (f=<error reading variable: Cannot access memory at address 0x0>, x=<error reading variable: Location address is not set.>, constr=...) at /home/runner/work/prima/prima/fortran/examples/cobyla/cobyla_example.f90:22 #1 0x00007ffff7f126e9 in calcfc_internal (f_internal=<error reading variable: Cannot access memory at address 0x0>, x_internal=<error reading variable: Location address is not set.>, constr_internal=...) at /home/runner/work/prima/prima/fortran/cobyla/cobylb.f90:667 #2 0x00007ffff7ed8891 in evaluate_mod::evaluatefc (calcfc=0x4155415641574155, f=0.04642817229746083, x=..., constr=...) at /home/runner/work/prima/prima/fortran/common/evaluate.f90:191 #3 0x00007ffff7f1b1b7 in initialize_cobyla_mod::initxfc (calcfc=<optimized out>, iprint=<optimized out>, maxfun=<optimized out>, ctol=<optimized out>, f0=<optimized out>, ftarget=<optimized out>, rhobeg=<optimized out>, nf=<optimized out>, info=<optimized out>, constr0=..., x0=..., chist=..., conhist=..., conmat=..., cval=..., fhist=..., fval=..., sim=..., simi=..., xhist=..., evaluated=...) at /home/runner/work/prima/prima/fortran/cobyla/initialize.f90:156 #4 0x00007ffff7f0e708 in cobylb_mod::cobylb (calcfc=<optimized out>, iprint=<optimized out>, maxfilt=<optimized out>, maxfun=<optimized out>, ctol=<optimized out>, cweight=<optimized out>, eta1=<optimized out>, eta2=<optimized out>, ftarget=<optimized out>, gamma1=<optimized out>, gamma2=<optimized out>, rhobeg=<optimized out>, rhoend=<optimized out>, f=<optimized out>, nf=<optimized out>, cstrv=<optimized out>, info=<optimized out>, amat=..., bvec=..., constr=..., x=..., chist=..., conhist=..., fhist=..., xhist=...) at /home/runner/work/prima/prima/fortran/cobyla/cobylb.f90:213 #5 0x00007ffff7f09224 in cobyla_mod::cobyla (calcfc=1096237397, m_nlcon=0, f=0.04642817229746083, cstrv=0, f0=0, nf=0, rhobeg=0, rhoend=0, ftarget=0, ctol=0, cweight=0, maxfun=0, iprint=0, eta1=0, eta2=0, gamma1=0, gamma2=0, maxhist=0, maxfilt=0, info=0, x=<error reading variable: value requires 750599937872512 bytes, which is more than max-value-size>, nlconstr=<error reading variable: Cannot access memory at address 0x0>, aineq=<error reading variable: value requires 6262704000 bytes, which is more than max-value-size>, bineq=..., aeq=<error reading variable: value requires 710976 bytes, which is more than max-value-size>, beq=..., xl=<error reading variable: value requires 17518252251111699504 bytes, which is more than max-value-size>, xu=..., nlconstr0=<error reading variable: value requires 6262704000 bytes, which is more than max-value-size>, xhist=<not allocated>, fhist=<not allocated>, chist=<not allocated>, nlchist=<not allocated>) at /home/runner/work/prima/prima/fortran/cobyla/cobyla.f90:600 #6 0x00005555555568ea in cobyla_exmp () at /home/runner/work/prima/prima/fortran/examples/cobyla/cobyla_example.f90:106
as for the argument packing, that was just to try if it can avoid another cobyla segfault on the C side
The segfault seems to be the same one as https://github.com/libprima/prima/issues/41
I guess it is a bug of aocc, but not sure, as I have not got the time to boil it down to a minimal example (I would be much grateful if you happen to be able to do it).
It has been reported to aocc https://community.amd.com/t5/server-gurus-discussions/aocc-4-1-flang-quot-0-allocate-xxx-bytes-requested-not-enough/m-p/623584#M2038 , but I don’t expect anyone will respond according to my previous experiences with aocc.
That said, we don’t fully support aocc for the moment, likely due to aocc's bug.
Great to hear your explanation about the packing. So I suppose it is for debugging only and will be de-packed in the final version.
Thank you.
Sorry for my ignorance about CMake. Where is the place to specify compiler options? The following options must be applied so that the local arrays and automatic arrays will be allocated on the heap, rather than on the stack. Otherwise, stack overflow may occur if the problem is sufficiently large.
AOCC Flang: nothing
Classic Flang: nothing
gfortran:
-fno-stack-arrays
ifort and ifx:
-heap-arrays
nagfor: nothing
nvfortran:
-Mnostack_arrays
Arm Flang:
-fno-stack-arrays
N.B.: In the context of derivative-free optimization, the computational cost is dominated by function evaluations (i.e.,
calfun
orcalcfc
), a single of which can take minutes, hours, days, or even months. Therefore, it makes no sense to worry about the performance difference between stack and heap in the implementation of the solvers.
Of course, it is always helpful to have -g
included during the debugging, or gdb
may not provide the full information. Thanks.
I set the stack array flags in the root CMakeLists then the cmake workflow script sets release mode + debug info (see CMAKE_BUILD_TYPE) so that adds -g
@zaikunzhang I disabled the cobyla test for now in the CI because of the aocc bug and possibly another one affecting all the 3 flang-based compilers (still investigating) do you think it is ready to be merged ?
See the :open_file_folder: files view, the :scroll:action log or :angel: SARIF report for details.
cobjcon
See the :open_file_folder: files view, the :scroll:action log or :angel: SARIF report for details.
cobjcon
Hi @jschueller ,
First of all, thank you very much for your efforts.
I made some comments. I would like to invite @ragonneau to help me review things again since I am not familiar enough with C.
Sorry to repeat this: I have a serious concern about the interfaces of COBYLA and LINCOA.
1. LINCOA should accept linear equality constraints as well.
2. COBYLA should accept linear constraints as well.
3. nlconstr
should be an output of COBYLA.
For anyone interested in these points, I attache at the end of this comment the explanations made before.
I hope to emphasize two things in addition.
1. While being vital, the above-mentioned points would not complicate the interfaces essentially. 2. Once the interfaces are released, it would be very difficult to make changes to them. Wide decisions must be made now.
Thank you very much.
Zaikun
OK. I may have to give some comments from the viewpoint of numerical optimization algorithms (beyond coding). Most of them have been mentioned above, but it might be better to reiterate and clarify them.
- If linear constraints are not exposed, then they will have to be passed as "black-box nonlinear constraints". The obvious disadvantages are as follows. 1.1. It hurts the performance, because the algorithms will not be able to explore the linear structure. 1.2. The users will have to wrap the linear constraints into "black-box nonlinear constraints". This is tedious and error-prone.
- Why is it a must to return the value of the nonlinear constraint? Powell's algorithms are designed for derivative-free optimization problems. Objective/constraint functions of such problems are generally expensive to evaluate --- it is not uncommon that a single function evaluation takes minutes or hours (sometimes days or even more). In addition to the constraint violation
cstrv
, it is natural that the user also wants to know the value of the nonlinear constraint at the solution. If we do not return this value, then the user would have to perform an expensive function evaluation (minutes, hours, days, or more) to calculate it, which is an obvious waste because this value was already evaluated.I believe that François @FrancoisGallard will agree with these two points. He is a practitioner that uses these algorithms in real projects. Maybe François could give some comments.
Thanks.
@zaikunzhang I disabled the cobyla test for now in the CI because of the aocc bug and possibly another one affecting all the 3 flang-based compilers (still investigating).
Do we still test cobyla when the compiler is not flang-based (i.e., gcc an ifort)? I hope so.
another one affecting all the 3 flang-based compilers
Could you direct me to the error log? On the pure fortran side, nvfortran
and Classic flang
do not have problems. AOCC flang
is a bit left behind due to the vendor(AMD) itself and we have no much to do.
I addition, I have self-hosted runners with access to nagfor
:
runs-on: [self-hosted, nagfor]
Would you mind adding a yml
that can make the tests on these runners using nagfor
? nagfor
is quite popular.
Thanks.
@FrancoisGallard and @jalvesz , you are also invited to give comments if interested. Thank you.
@zaikunzhang do you think the C interface is ok for you ? I was thinking maybe it could be merged.
The Python part probably still needs discussion though, that's why I removed it for now, but I can still propose it in a later PR if needed, waiting for a pure Python implementation (#37). 0001-Add-Python-binding.txt
The Python interface is of high importance. Making the solvers available in SciPy has a high priority. So yes, please propose it in a later PR.
A pure Python implementation is being worked on, but it is highly nontrivial, and sufficiently extensive tests are needed. I believe SciPy has to interface with the Fortran implementation first. Thanks.
Thank you @jschueller for working on the new version.
nlconstr_loc
is better declared as nlconstr_loc(m_nlcon)
.
Indeed, since we enforce the automatic arrays to be allocated on the heap, the code behaves essentially the same as using an allocatable array. But it is more expressive, saves two lines, and eliminates the possibility of memory leaking.
Thanks.
Thank you @jschueller for working on the new version.
nlconstr_loc
is better declared asnlconstr_loc(m_nlcon)
.Indeed, since we enforce the automatic arrays to be allocated on the heap, the code behaves essentially the same as using an allocatable array. But it is more expressive, saves two lines, and eliminates the possibility of memory leaking.
Thanks.
this doesnt work since the cobyla function wants an allocatable argument and if I specify the size it says it should have deferred shape
This adds a C interface to the Fortran library thanks to the iso_c_binding module:
prima.h:
Some fortran modules have to be renamed to allow building everything into one single fortran library.
This also introduces a CMake build system to build both the Fortran library and the C library in a cross-platform manner.
Comments welcome