Skip to content
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

Rounding mode switching side-effects #155

Open
fkonvick opened this issue Jul 15, 2022 · 3 comments
Open

Rounding mode switching side-effects #155

fkonvick opened this issue Jul 15, 2022 · 3 comments

Comments

@fkonvick
Copy link

When running a model involving FloatVars, the FPU rouding mode may get changed, which may cause issues with code running afterwards. This happens with Gecode 6.2.0 (I haven't checked whether this changed in 6.3 yet).

I'm not certain which platforms this applies to, but it certainly happened to me on Linux x64 and, in the past, on Windows (I wasn't able to reproduce this now).

I created the following simple "guard class" to work around this problem.

struct SaveRoundingState {
  Gecode::Float::Rounding::rounding_mode original_rt;
  SaveRoundingState() {
    Gecode::Float::Rounding::get_rounding_mode(original_rt);
  }
  ~SaveRoundingState() {
    Gecode::Float::Rounding::set_rounding_mode(original_rt);
  }
};

Using this as follows resolves the issue (including printouts of the rounding mode):

{
  Gecode::Float::Rounding::rounding_mode rm;
  Gecode::Float::Rounding::get_rounding_mode(rm);
  std::cout << rm << "\n";
  {
    SaveRoundingState save_state;
    // (run the solver)
  }
  Gecode::Float::Rounding::get_rounding_mode(rm);
  std::cout << rm << "\n";
}

In any case I think that Gecode should be cleaning up by itself.

@zayenz
Copy link
Member

zayenz commented Jul 18, 2022

Interesting issue, thanks for bringing it up. There are no recent changes to how this code operates, so nothing new to be expected in 6.3.

I agree that we should probably be more careful with how we set and manage the rounding mode for Gecode. One issue is that there is no outermost entry-point into Gecode proper where an automatic method would naturally fit in. As an alternative, creating a helper-class to use outside as you show above is a simple solution, but it also requires knowledge by the user.

Let's think some more on this, to see if there is a good solution that makes it easier for users.

I know that there are additional problems with rounding modes, and that these can change outside of the programs control as it is essentially shared mutable state of the CPU. In discussions with others that do serious work with floating point computations, I've heard of systems going so far as to set the rounding mode immediately before each computation. I think this is probably overkill for Gecode, but I just thought I should mention it as an expanded viewpoint.

@fkonvick
Copy link
Author

I agree on all points. I did not expect a quick solution for 6.3.0 as the issue has apparently existed for quite some time. I will try to create some minimal example code to allow testing.
The solution should ideally allow Gecode to set up the rounding mode once (to prevent that each computation needs to set the rounding mode anew).

@zayenz
Copy link
Member

zayenz commented Jul 24, 2022

I fully agree that it would be good to have a simple built-in way to set the rounding mode that can be recommended. If you can figure out a good way to package that, that would be a great addition.

For the record, only setting it before using any Gecode code might not be enough in all cases. Consider a user that writes a custom logic propagator that uses, for example, an in-house dynamic library for price calculations. That library might set the rounding mode and not re-set it afterwards. In other words, the same type of guard logic saving and restoring the rounding mode would be valuable to use around any external calls.

The above reasoning is why I've heard that some libraries are very cautious and spend a lot of time ensuring that the rounding mode is always set - as a library the user may have any kind of code running concurrently with the library code in the same process. For Gecode I think that that level of caution would be overkill, and that your proposed solution would be a good level of abstraction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants