the first thing I was wondering was the fact that you mention that you can imagine that your users are more annoyed by it than you are, this seems like a perfect opportunity to go and figure that out, in the field :-)
I don't get why somebody would want to press the "cancel button", as there is, according to you, not much else they can do. There is some level of control added though, but to what purpose? I expect that one does the calculation, because that's his goal for that day.
Anyway, if the user could do anything else, you could consider putting it in a visual queue or something, so that the user may continue doing something else while he can check and see the progress of that calculation (in the upper corner for instance).
Something you should do, is warn the user that executing that action will take a very long time to calculate and that they won't be able to do anything else in the meanwhile.
You could also try to give an estimation of how long the calculation will probably run, and put the estimated countdown under the spinner. But in the end, it will always be more qualitative to figure out the time it will last. One thing you should than take into account, is the fact that it should simply move, eventhough it might be slow, some movement is better than none.
Sources: