Message Boards Message Boards

0
|
7457 Views
|
3 Replies
|
0 Total Likes
View groups...
Share
Share this post:

RuntimeErrorHandler and Check[] in combination with CompiledFunction[]

Posted 9 years ago

Hi, I use Mathematica 10.0 and have following code where I want to stop the calculation if a CompiledFunction generates an error message:

offset = 4;(*3=ok, 4=error*)
func1 = Compile[{{v, _Real}}, Block[{r}, r = Sqrt[v - offset]], "RuntimeOptions" -> {"RuntimeErrorHandler" -> Function[Throw[$Failed]]}];
Off[General::stop];(*enable or disable, does not matter*)
Map[Catch[func1[#]] &, Range[10]]
On[General::stop];

Previous code works fine as long as no more than 3 messages are created, but starting from the 4th message only the RuntimeErrorHandler seems to be executed although the result should be valid. Switching off the "General::stop" message has no effect on the behaviour of the above code.

When I use Check[] instead of the RuntimeErrorHandler the behaviour is such that the first 3 messages are catched by Check[] but no further message is generated at all. The function returns complex numbers which must have been evaluated silently by non-compiled code.

offset = 5;(*3=ok, 4=ok(?), 5=complex results from non-compliled code?*)
func2 = Compile[{{v, _Real}}, Block[{r}, r = Sqrt[v - offset]]];
Off[General::stop];(*enable or disable,does not matter*)
Map[Check[func2[#], "error"] &, Range[10]]
On[General::stop];

A note why I want to catch messages from compiled code: I thought its a clever idea to use a compiled function with variables set to Reals which will generate an error whenever it starts to generate complex numbers - which are useless for me. In this case I would like to abort any evaluation immediately without loss of time (I am doing a computational heavy simulation).

What is your opinion? Is it a bug or do I do something wrong? Thanks a lot for your comments. Andreas

3 Replies

Hi Udo, thank you for your work-around!

I can confirm your observations (on Win7 64bit, Mathematica 10.0.2.0). Your work-around works like a charm.

It also works with a throwing error handler:

In[351]:= Remove[func27]
func27 = Compile[{{v, _Real}}, Sqrt[v - 27], "RuntimeOptions" -> {"RuntimeErrorHandler" -> Function[Throw[$Failed]]}];
If[True,(*if True unfreak the error handler, otherwise get always $Failed below*)
  Catch[func27[#]] & /@ {1, 27}
  ];
(*works if True above*)
Catch[func27[#]] & /@ Range[23, 30]
Out[354]= {$Failed, $Failed, $Failed, $Failed, 0., 1., 1.41421, 1.73205}

The work-around works also using Check:

In[313]:=Remove[func28]
func28 = Compile[{{v, _Real}}, Block[{r}, r = Sqrt[v - 28]]];
If[True,(*if True unfreak the error handler, otherwise get complex numbers below after 3x"error"*)
  func28[#] & /@ {1, 28}
  ];
Map[Check[func28[#], "error"] &, Range[24, 30]]    
Out[316]= {"error", "error", "error", "error", 0., 1., 1.41421}

I have sent a bug report to Wolfram Support. Andreas

This is for sure a bug. You strictly followed The Wolfram System Compiler tutorial, entry Runtime Error Handling in the tool. On the web there is a description without Throw.

The thing is, after having thrown one error followed by an errorless evaluation, you can later on throw as much as you want.

   In[1]:= Remove[func8]
    func8 = Compile[{{v, _Real}}, Sqrt[v - 8], "RuntimeOptions" -> {"RuntimeErrorHandler" -> Function[Throw[$Failed]]}]

Out[2]= CompiledFunction[{10, 10., 4444}, {
Blank[Real]}, {{3, 0, 0}, {3, 0, 1}}, {{-8, {2, 0, 
   0}}}, {0, 1, 3, 0, 0}, {{10, 0, 1}, {13, 0, 1, 2}, {40, 57, 3, 0, 
  2, 3, 0, 1}, {1}}, Function[{v}, Sqrt[v - 8]], Throw[$Failed]& ]

In[3]:= Catch[func8[#]] & /@ {1, 15, 16, 17, 18}
During evaluation of In[3]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>   
Out[3]= {$Failed, 2.64575, 2.82843, 3., 3.16228}

In[4]:= Catch[func8[#]] & /@ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 15, 16, 17, 18}
During evaluation of In[4]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>
During evaluation of In[4]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>
During evaluation of In[4]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>
During evaluation of In[4]:= General::stop: Further output of CompiledFunction::cfn will be suppressed during this calculation. >>

Out[4]= {$Failed, $Failed, $Failed, $Failed, $Failed, $Failed, \
$Failed, $Failed, $Failed, $Failed, $Failed, $Failed, $Failed, \
2.64575, 2.82843, 3., 3.16228}

If you throw 3 errors in the beginning, it will never work again, even with offset = 3:

In[8]:= Remove[func3]
func3 = Compile[{{v, _Real}}, Sqrt[v - 3], "RuntimeOptions" -> {"RuntimeErrorHandler" -> Function[Throw[$Failed]]}]

Out[9]= CompiledFunction[{10, 10., 4444}, {
Blank[Real]}, {{3, 0, 0}, {3, 0, 1}}, {{-3, {2, 0, 
   0}}}, {0, 1, 3, 0, 0}, {{10, 0, 1}, {13, 0, 1, 2}, {40, 57, 3, 0, 
  2, 3, 0, 1}, {1}}, 
Function[{v}, Sqrt[v - 3]], Throw[$Failed]& ]

In[10]:= Catch[func3[#]] & /@ {1, 1, 1, 5, 6, 7, 8}
During evaluation of In[10]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>
During evaluation of In[10]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>
During evaluation of In[10]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>
During evaluation of In[10]:= General::stop: Further output of CompiledFunction::cfn will be suppressed during this calculation. >>

Out[10]= {$Failed, $Failed, $Failed, $Failed, $Failed, $Failed, $Failed}

Do this again in the same session

In[14]:= Remove[func31]
func31 = Compile[{{v, _Real}}, Sqrt[v - 3], "RuntimeOptions" -> {"RuntimeErrorHandler" -> Function[Throw[$Failed]]}]

Out[15]= CompiledFunction[{10, 10., 4444}, {
Blank[Real]}, {{3, 0, 0}, {3, 0, 1}}, {{-3, {2, 0, 
   0}}}, {0, 1, 3, 0, 0}, {{10, 0, 1}, {13, 0, 1, 2}, {40, 57, 3, 0, 
  2, 3, 0, 1}, {1}}, 
Function[{v}, Sqrt[v - 3]], Throw[$Failed]& ]

In[16]:= Catch[func31[#]] & /@ {1, 5, 6, 7, 8}
During evaluation of In[16]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>
Out[16]= {$Failed, 1.41421, 1.73205, 2., 2.23607}

In[17]:= Catch[func31[#]] & /@ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6,7, 8}
During evaluation of In[17]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>
During evaluation of In[17]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>

During evaluation of In[17]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>
During evaluation of In[17]:= General::stop: Further output of CompiledFunction::cfn will be suppressed during this calculation. >>

Out[17]= {$Failed, $Failed, $Failed, $Failed, $Failed, $Failed, \
$Failed, $Failed, $Failed, $Failed, $Failed, 1.41421, 1.73205, 2., \2.23607}

that works. Condition seems to be: Generate one or two errors then an errorless evaluation and now you can do whatever you want:

Remove[func17]
func17 = Compile[{{v, _Real}}, Sqrt[v - 17], "RuntimeOptions" -> {"RuntimeErrorHandler" -> Function[$Failed]}]

In[31]:= func17 /@ {1, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 22,23, 24}

During evaluation of In[31]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>
During evaluation of In[31]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>
During evaluation of In[31]:= CompiledFunction::cfn: Numerical error encountered at instruction 3; proceeding with uncompiled evaluation. >>
During evaluation of In[31]:= General::stop: Further output of CompiledFunction::cfn will be suppressed during this calculation. >>

Out[31]= {$Failed, 1.73205, $Failed, $Failed, $Failed, $Failed, $Failed, $Failed, $Failed, $Failed, $Failed, $Failed, $Failed, \
$Failed, 2., 2.23607, 2.44949, 2.64575}

This is Mathematica 10.0.2.0 under Windows 7 64 Bit Home Premium. Consider to file a bug to Wolfram, please.

POSTED BY: Udo Krause

As a work-around you can do this

In[6]:= Remove[func17]
func17 = Compile[{{v, _Real}}, Sqrt[v - 17], "RuntimeOptions" -> {"RuntimeErrorHandler" -> Function[$Failed]}];
Off[CompiledFunction::cfn]
(* unfreak the error handler *)
func17 /@ {1, 20};

In[10]:= func17 /@ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 22, 23,24}
Out[10]= {$Failed, $Failed, $Failed, $Failed, $Failed, $Failed, \
$Failed, $Failed, $Failed, $Failed, $Failed, $Failed, $Failed, 2., \
2.23607, 2.44949, 2.64575}

to have it working like a charme. But that work-around seems to fail with a throwing error handler.

POSTED BY: Udo Krause
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract