I have recently been testing the performance of SELECT CASE. Specifically, how it performs when I use integer variables as the branching expression vs. strings. I am noticing some odd performance.
I have a DO loop that loops over a simple SELECT CASE statment, like this
INTEGER :: i
CHARACTER(len=8) :: string_var
string_var = 'someText'
DO i = 1, 100000000
SELECT CASE (string_var)
CASE ('string1')
a = 1
CASE ('string2')
a = 1
.
.
.
CASE ('someText')
a = 1
CASE DEFAULT
a = 1
END SELECT
END DO
When I execute this using a Release-compiled version, performance is relatively fast (0.44 sec). A similar SELECT CASE using integers instead of strings is even faster. But here is the weird part. If I replace the "a=1" statement in CASE DEFAULT
with
print *, 'no equivalent string'
run time slows to 3.25 secs, even though the print statement is never actually executed. If I add the print statement to the SELECT CASE using integers, I do not see this performance hit.
Why does this happen? Or am I doing something wrong?
Thanks in advance,
Chris
I have a DO loop that loops over a simple SELECT CASE statment, like this
INTEGER :: i
CHARACTER(len=8) :: string_var
string_var = 'someText'
DO i = 1, 100000000
SELECT CASE (string_var)
CASE ('string1')
a = 1
CASE ('string2')
a = 1
.
.
.
CASE ('someText')
a = 1
CASE DEFAULT
a = 1
END SELECT
END DO
When I execute this using a Release-compiled version, performance is relatively fast (0.44 sec). A similar SELECT CASE using integers instead of strings is even faster. But here is the weird part. If I replace the "a=1" statement in CASE DEFAULT
with
print *, 'no equivalent string'
run time slows to 3.25 secs, even though the print statement is never actually executed. If I add the print statement to the SELECT CASE using integers, I do not see this performance hit.
Why does this happen? Or am I doing something wrong?
Thanks in advance,
Chris
链接已复制
4 回复数
I think you will find that the compiler decided to optimize the entire SELECT CASE (or even DO loop) away, since it could fold the whole thing into an a=1 statement.
Adding the PRINT meant that it couldn't do that.
In other words, you aren't measuring what you think you are measuring.
Steve
Adding the PRINT meant that it couldn't do that.
In other words, you aren't measuring what you think you are measuring.
Steve
That certainly seems like it would explain it, although my spidey sense is still tingling.
Before playing around with the print statement, I tested the following 3 SELECT CASE configurations
integer_var = 10
SELECT CASE (integer_var)
CASE (1)
a=1
.
.
.
CASE (10)
a=1
CASE DEFAULT
a=1
END SELECT
char_var = 'someText'
SELECT CASE (char_var)
CASE ('string1')
a=1
.
.
.
CASE ('someText')
a=1
CASE DEFAULT
a=1
END SELECT
char_var2 = 'someText '
SELECT CASE (TRIM(char_var2))
CASE ('string1')
a=1
.
.
.
CASE ('someText')
a=1
CASE DEFAULT
a=1
END SELECT
Results were (over 100,000,000 iterations)
config 1 - 0.00 cpu secs (below resolution of my timer)
config 2 - 0.44 cpu secs
config 3 - 7.39 cpu secs
If the compiler was recognizing that "a=1" in all cases, and optimizing the SELECT CASE away, shouldn't I have seen the same performance in all 3 cases?
At any rate, having differing statements in each CASE is a better approach for this sort of benchmarking since it is closer to what would happen in the real world.
Thanks,
Chris
Before playing around with the print statement, I tested the following 3 SELECT CASE configurations
integer_var = 10
SELECT CASE (integer_var)
CASE (1)
a=1
.
.
.
CASE (10)
a=1
CASE DEFAULT
a=1
END SELECT
char_var = 'someText'
SELECT CASE (char_var)
CASE ('string1')
a=1
.
.
.
CASE ('someText')
a=1
CASE DEFAULT
a=1
END SELECT
char_var2 = 'someText '
SELECT CASE (TRIM(char_var2))
CASE ('string1')
a=1
.
.
.
CASE ('someText')
a=1
CASE DEFAULT
a=1
END SELECT
Results were (over 100,000,000 iterations)
config 1 - 0.00 cpu secs (below resolution of my timer)
config 2 - 0.44 cpu secs
config 3 - 7.39 cpu secs
If the compiler was recognizing that "a=1" in all cases, and optimizing the SELECT CASE away, shouldn't I have seen the same performance in all 3 cases?
At any rate, having differing statements in each CASE is a better approach for this sort of benchmarking since it is closer to what would happen in the real world.
Thanks,
Chris
I'd guess that in the third case, the compiler didn't realize that the result of the TRIM could be discarded. Even if you use different statements, if you never use A after the CASE, the compiler can still throw it all away.
Which compiler are you using?
Steve
Which compiler are you using?
Steve
