I mostly agree with Cliff's conclusions, but I disagree with some of the
arguments:
>
> Maybe I'll answer your questions in reverse order, since the
> answer to the
> last answers most of the rest. The answer is: we have
> different cost metrics
> so what's right for "me" isn't nessecarily what's right for
> "you". Here "me"
> is Sun & it's efforts to improve the Java experience for the
> bulk of it's users
> (even if a few users have to suffer); part of that
> improvement effort is making
> benchmarks run fast so, e.g. Microsoft, doesn't get the
> chance to splinter the
> market based on performance. Here "you" is a competent programmer who
> wishes to understand how the JVM & compiler work so you can write code
> that will behave as expected, especially wrt optimization and
> synchronization.
It seems to me that compilers should actually strive toward two goals:
1) Performance on current code.
2) Some level of performance predictability.
If I don't have (2), i.e. I can't predict the performance impact of code
changes to at least some extent, I lose the ability to improve the
performance of my code over time. It might not show up in benchmarks, and
it's much harder to measure, but in the long run, I think (2) also has a
significant impact on application performance. Punishing well-written,
efficient code in order to improve performance of sloppy code is dangerous.
Having the compiler mess with lock hold times while I try to tune for MP
scalability is clearly an issue for (2), but I think Cliff has argued
convincingly that there are cases in which it's still worthwhile and the
downside is relatively small.
>
> A motivating example is find in the SciMark benchmark suite,
> which copped
> a rather stock psuedo random number generator for use in a Monte Carlo
> simulation. The generator is sync'd on reading and writing
> the internal state
> so multi-threaded programs don't "reset" the generator back a
> few numbers or
> blow the generator properties by mixing up the hidden state
> between numbers.
> The generator is otherwise quite fast, which means the cost
> of sync'ing dominates;
> since this is a Monte Carlo simulation, the program spends
> most of it's time
> locking & unlocking the generator in a tight loop with very
> little work between
> calls to the generator. It's all nice clean well abstracted
> code that was never
> meant to be in an inner loop.
>
I strongly disagree with the last sentence. I looked at the benchmark. In
this respect it looks like bad code. It's not a clean abstraction. It
needs to be fixed. It doesn't belong in a benchmark. (The authors are in
the best of company, though. This sort of thing clearly gets written all
the time. That's why it's important to point out that it's bad interface
design.)
There is no reason to synchronize access to the random number generator.
It's Java code, so no safety properies can be violated with unsynchronized
concurrent access. (Presumably no safety properties depend on the outcome
of a random number generator.) If the code were not synchronized, the client
could choose to use either per-thread random number generators, or to
synchronize access to a global one. (The interface is otherwise nicely
designed to make both possible. The actual benchmark uses the former
model.) As it stands, reasonable performance for multithreaded simulations
is needlessly excluded. Even if my compiler manages to eliminate the
synchronizations, some other compiler waon't, thus effectively making the
code unportable if I care about performance.
General purpose libraries should almost always leave synchronization to the
client, unless that violates some safety properties.
Hans
-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:30 EDT