relf / cobyla

COBYLA optimizer for Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Using iprint = 0 negatively influences the performance

Sven-MintTower opened this issue · comments

Using the function fmin_cobyla the iprint variable influences the performance non-trivially. Putting iprint to 0 reduces the performance by a factor of 100x. Whereas iprint is 1,2,3 perform in line. (1 being the fastest due to less printing)

Weird! I've tried on the paraboloid example. It runs in ~10ms +/- 5ms on my machine whatever the iprint value, anyway I am far from seeing a x100 factor. Could you provide info on your setup and the code showing the problem?

Unfortunately, I cannot provide my current setup. However, I think we have fixed it. In src/cobyla.rs line 523 should be an if statement around the println!. Now the current_block is not set and the loop isn't broken if iprint is set to 0.

Sorry, I am not sure to understand your fix. Could you copy it here?

if nfvals >= maxfun
    && nfvals > 0 as libc::c_int as libc::c_long {
                  
    status = -(2 as libc::c_int);
    if iprint > 0 as libc::c_int as libc::c_long { 
       println!("Return from subroutine COBYLA because {:?}.\n",
                    cobyla_reason(status));
    };
    current_block = 2880604979707412946;
    break;

Hmmm... If there is a bug it seems to come from the original code (the iprint>0 condition is tested with the others)
a) original c code :

if (nfvals >= maxfun && nfvals > 0 && iprint > 0) {

b) rust code from c2rust:
if nfvals >= maxfun && nfvals > 0 as libc::c_int as libc::c_long

c) edited rust code:
if nfvals >= maxfun

I agree that your fix is relevant as changing the verbosity should not change the logic like the status setting. On your test case if iprintf is set to zero, the algorithm still terminates? What is the value of the status then?

With the bug: the algorithm indeed still terminates. However, with status -2 mostly.
Without the bug: the algorithm also still terminates. But, with significantly more zeros as status.

The translation of the Fortran to C. The Fortan code of scipy doesn't seem to have this bug. https://github.com/scipy/scipy/blob/686422c4f0a71be1b4258309590fd3e9de102e18/scipy/optimize/cobyla/cobyla2.f#L141C4-L141C4 IF (NFVALS .GE. MAXFUN .AND. NFVALS .GT. 0) THEN IF (IPRINT .GE. 1) PRINT 50 50 FORMAT (/3X,'Return from subroutine COBYLA because the ', 1 'MAXFUN limit has been reached.') DINFO(1)=2.0d0 GOTO 600

My bad! I've finally found, I've introduced this bug in the commit 409d753 😔 Maybe a leftover for a test/debug session... Do not remember. The original code did not test iprint at all at this point.
I will issue a release with your fix.
Thanks for the good catch!

Just to notice that the bug is present at another line:

&& iprint > 0 as libc::c_int as libc::c_long

The C code includes itself at some point, hence the duplication in the Rust code.