Hi, I've search the archives for "short circuit" but did not find an answer.
So I am posting here.

Consider the following code (app.pyx):

  from hashlib import sha1

  cdef long expensive(long n, long k):
    return long(sha1("%s:%s" % (n, k)).hexdigest()[:4], base=16) < 256

  def test1(long n):
    cdef long i, sum = 0
    for i in range(n):
      if expensive(i, 0) and expensive(i, 1): # short-circuit
        sum += i
    print sum

  def test2(long n):
    cdef long i, sum = 0
    for i in range(n):
      if expensive(i, 0): # nested-if
        if expensive(i, 1):
          sum += i
    print sum

If this was pure Python, the performance of test1() and test2() would be the
same. However with Cython, test1() was twice as slow as test2().

Looking at app.c:

  //    if expensive(i, 0) and expensive(i, 1):             # <<<<<<<<<<<<<<
      if (__pyx_f_3app_expensive(__pyx_v_i, 0)) {
        __pyx_t_2 = __pyx_f_3app_expensive(__pyx_v_i, 1);
      } else {
        __pyx_t_2 = __pyx_f_3app_expensive(__pyx_v_i, 0);
      }

and

  //    if expensive(i, 0):             # <<<<<<<<<<<<<<
      __pyx_t_2 = __pyx_f_3app_expensive(__pyx_v_i, 0);
      if (__pyx_t_2) {

  //      if expensive(i, 1):             # <<<<<<<<<<<<<<
        __pyx_t_2 = __pyx_f_3app_expensive(__pyx_v_i, 1);
        if (__pyx_t_2) {

For the short-circuit version, the first test is sometimes evaluated twice.
For the nested-if version, it is evaluated exactly once.

Q: For the short-circuit, would the right behaviour be to store the result
of the first evaluation in a temporary variable instead?

I am new to Cython so pardon me if this is not the right place to ask. If a
patch is preferred, I can give it a try although I will take some time to
get familiar with the code.

Swee Heng
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to