Amaury Forgeot d'Arc, 03.07.2012 14:55:
> 2012/7/3 Stefan Behnel
>> I've been working with one of the modules in the Python benchmark suite,
>> namely nbody, and tried to make it run a little faster when compiled with
>> Cython in PyPy. I managed to get a massive speed-up by avoiding some
>> borrowed references during list iteration and using PySequence_GetItem()
>> instead, but now some 50-60% of the runtime are spent in Py_DecRef().
> 
> Don't forget that cpyext reference counts are quite different from CPython:
> PySequence_GetItem() needs to *create* a PyObject structure, and the
> returned object has a refcount of 1.
> Then Py_DECREF() will really *deallocate* the PyObject structure...

Sure. And using PySequence_GetItem() is still some 10x faster in PyPy than
taking a borrowed reference using PyList_GET_ITEM() and then calling
Py_INCREF() on it, which is what Cython does in CPython because it's way
faster there. The overhead of borrowed references is seriously huge in PyPy.

BTW, are PyObject structures currently cached in a free-list somewhere?
That would be really helpful for the iteration performance.


> This is quite more expensive than the simple refcount increment/decrement
> done by CPython.
> 
>> OverflowError: array too large
> 
> Looks like a ctypes bug to me. Which OS, Python, etc. are you using?

Ah - totally, sure. I accidentally ran the system Py2.5 on 64bit Linux.
Running it with Py2.7 fixes this specific problem, thanks for the hint!
Although it now names the extension module "nbody.so" instead of
"nbody.pypy-19.so". Comprend qui peut ...

After figuring out that I was supposed to enable cpyext manually and
running strace to see what extension module name it is actually looking
for, I failed to make it load the module it just built regardless of how I
named it, so I tried building it within the same run as follows:

  pypy/bin/py.py --withmod-cpyext -c 'import setup; import nbody; \
                                      nbody.test_nbody(1)'  build_ext -i

Doing this, it then fails with the following error:

"""Traceback (most recent call last):
  File ".../pypy/bin/py.py", line 187, in <module>
    sys.exit(main_(sys.argv))
  File ".../pypy/bin/py.py", line 158, in main_
    verbose=interactiveconfig.verbose):
  File ".../pypy/interpreter/main.py", line 103, in run_toplevel
    f()
  File ".../pypy/bin/py.py", line 133, in doit
    main.run_string(command, space=space)
  File ".../pypy/interpreter/main.py", line 59, in run_string
    _run_eval_string(source, filename, space, False)
  File ".../pypy/interpreter/main.py", line 48, in _run_eval_string
    retval = pycode.exec_code(space, w_globals, w_globals)
  File ".../pypy/interpreter/eval.py", line 33, in exec_code
    return frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 834, in IMPORT_NAME
    w_locals, w_fromlist)
  File ".../pypy/interpreter/baseobjspace.py", line 986, in call_function
    return w_func.funccall(*args_w)
  File ".../pypy/interpreter/function.py", line 111, in funccall
    return self.call_args(Arguments(self.space, list(args_w)))
  File ".../pypy/interpreter/function.py", line 59, in call_args
    return self.getcode().funcrun(self, args)
  File ".../pypy/interpreter/gateway.py", line 614, in funcrun
    return BuiltinCode.funcrun_obj(self, func, None, args)
  File ".../pypy/interpreter/gateway.py", line 631, in funcrun_obj
    self.handle_exception(space, e)
  File ".../pypy/interpreter/gateway.py", line 648, in handle_exception
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/gateway.py", line 622, in funcrun_obj
    w_result = activation._run(space, scope_w)
  File "<6076-codegen .../pypy/tool/sourcetools.py:174>", line 3, in _run
  File ".../pypy/module/imp/importing.py", line 271, in importhook
    fromlist_w, tentative=True)
  File ".../pypy/module/imp/importing.py", line 297, in absolute_import
    fromlist_w, tentative)
  File ".../pypy/module/imp/importing.py", line 306, in
absolute_import_with_lock
    fromlist_w, tentative)
  File ".../pypy/module/imp/importing.py", line 367, in _absolute_import
    tentative=tentative)
  File ".../pypy/module/imp/importing.py", line 646, in load_part
    w_mod = load_module(space, w_modulename, find_info)
  File ".../pypy/module/imp/importing.py", line 601, in load_module
    find_info.stream.readall())
  File ".../pypy/module/imp/importing.py", line 911, in load_source_module
    exec_code_module(space, w_mod, code_w)
  File ".../pypy/module/imp/importing.py", line 872, in exec_code_module
    code_w.exec_code(space, w_dict, w_dict)
  File ".../pypy/interpreter/eval.py", line 33, in exec_code
    return frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 1029, in CALL_FUNCTION
    self.call_function(oparg)
  File ".../pypy/interpreter/pyopcode.py", line 1012, in call_function
    w_result = self.space.call_args(w_function, args)
  File ".../pypy/objspace/descroperation.py", line 158, in call_args
    return w_obj.call_args(args)
  File ".../pypy/interpreter/function.py", line 59, in call_args
    return self.getcode().funcrun(self, args)
  File ".../pypy/interpreter/pycode.py", line 210, in funcrun
    return frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 1022, in CALL_FUNCTION
    w_result = self.space.call_valuestack(w_function, nargs, self)
  File ".../pypy/interpreter/baseobjspace.py", line 1015, in call_valuestack
    return w_func.funccall_valuestack(nargs, frame)
  File ".../pypy/interpreter/function.py", line 147, in funccall_valuestack
    return self._flat_pycall(code, nargs, frame)
  File ".../pypy/interpreter/function.py", line 172, in _flat_pycall
    return new_frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 1022, in CALL_FUNCTION
    w_result = self.space.call_valuestack(w_function, nargs, self)
  File ".../pypy/interpreter/baseobjspace.py", line 1015, in call_valuestack
    return w_func.funccall_valuestack(nargs, frame)
  File ".../pypy/interpreter/function.py", line 147, in funccall_valuestack
    return self._flat_pycall(code, nargs, frame)
  File ".../pypy/interpreter/function.py", line 172, in _flat_pycall
    return new_frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 1022, in CALL_FUNCTION
    w_result = self.space.call_valuestack(w_function, nargs, self)
  File ".../pypy/interpreter/baseobjspace.py", line 1015, in call_valuestack
    return w_func.funccall_valuestack(nargs, frame)
  File ".../pypy/interpreter/function.py", line 147, in funccall_valuestack
    return self._flat_pycall(code, nargs, frame)
  File ".../pypy/interpreter/function.py", line 172, in _flat_pycall
    return new_frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 1022, in CALL_FUNCTION
    w_result = self.space.call_valuestack(w_function, nargs, self)
  File ".../pypy/interpreter/baseobjspace.py", line 1015, in call_valuestack
    return w_func.funccall_valuestack(nargs, frame)
  File ".../pypy/interpreter/function.py", line 147, in funccall_valuestack
    return self._flat_pycall(code, nargs, frame)
  File ".../pypy/interpreter/function.py", line 172, in _flat_pycall
    return new_frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 1022, in CALL_FUNCTION
    w_result = self.space.call_valuestack(w_function, nargs, self)
  File ".../pypy/interpreter/baseobjspace.py", line 1015, in call_valuestack
    return w_func.funccall_valuestack(nargs, frame)
  File ".../pypy/interpreter/function.py", line 147, in funccall_valuestack
    return self._flat_pycall(code, nargs, frame)
  File ".../pypy/interpreter/function.py", line 172, in _flat_pycall
    return new_frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 1029, in CALL_FUNCTION
    self.call_function(oparg)
  File ".../pypy/interpreter/pyopcode.py", line 1012, in call_function
    w_result = self.space.call_args(w_function, args)
  File ".../pypy/objspace/descroperation.py", line 160, in call_args
    return w_obj.call_args(args)
  File ".../pypy/interpreter/function.py", line 471, in call_args
    return space.call_obj_args(self.w_function, self.w_instance, args)
  File ".../pypy/interpreter/baseobjspace.py", line 961, in call_obj_args
    return w_callable.call_obj_args(w_obj, args)
  File ".../pypy/interpreter/function.py", line 63, in call_obj_args
    return self.getcode().funcrun_obj(self, w_obj, args)
  File ".../pypy/interpreter/pycode.py", line 223, in funcrun_obj
    return frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 1022, in CALL_FUNCTION
    w_result = self.space.call_valuestack(w_function, nargs, self)
  File ".../pypy/interpreter/baseobjspace.py", line 1015, in call_valuestack
    return w_func.funccall_valuestack(nargs, frame)
  File ".../pypy/interpreter/function.py", line 147, in funccall_valuestack
    return self._flat_pycall(code, nargs, frame)
  File ".../pypy/interpreter/function.py", line 172, in _flat_pycall
    return new_frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 1022, in CALL_FUNCTION
    w_result = self.space.call_valuestack(w_function, nargs, self)
  File ".../pypy/interpreter/baseobjspace.py", line 1015, in call_valuestack
    return w_func.funccall_valuestack(nargs, frame)
  File ".../pypy/interpreter/function.py", line 147, in funccall_valuestack
    return self._flat_pycall(code, nargs, frame)
  File ".../pypy/interpreter/function.py", line 172, in _flat_pycall
    return new_frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 1029, in CALL_FUNCTION
    self.call_function(oparg)
  File ".../pypy/interpreter/pyopcode.py", line 1012, in call_function
    w_result = self.space.call_args(w_function, args)
  File ".../pypy/objspace/descroperation.py", line 158, in call_args
    return w_obj.call_args(args)
  File ".../pypy/interpreter/function.py", line 59, in call_args
    return self.getcode().funcrun(self, args)
  File ".../pypy/interpreter/pycode.py", line 210, in funcrun
    return frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 1029, in CALL_FUNCTION
    self.call_function(oparg)
  File ".../pypy/interpreter/pyopcode.py", line 1012, in call_function
    w_result = self.space.call_args(w_function, args)
  File ".../pypy/objspace/descroperation.py", line 158, in call_args
    return w_obj.call_args(args)
  File ".../pypy/interpreter/function.py", line 59, in call_args
    return self.getcode().funcrun(self, args)
  File ".../pypy/interpreter/pycode.py", line 210, in funcrun
    return frame.run()
  File ".../pypy/interpreter/pyframe.py", line 141, in run
    return self.execute_frame()
  File ".../pypy/interpreter/pyframe.py", line 175, in execute_frame
    executioncontext)
  File ".../pypy/interpreter/pyopcode.py", line 84, in dispatch
    next_instr = self.handle_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 107, in handle_bytecode
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/pyopcode.py", line 90, in handle_bytecode
    next_instr = self.dispatch_bytecode(co_code, next_instr, ec)
  File ".../pypy/interpreter/pyopcode.py", line 265, in dispatch_bytecode
    res = meth(oparg, next_instr)
  File ".../pypy/interpreter/pyopcode.py", line 1022, in CALL_FUNCTION
    w_result = self.space.call_valuestack(w_function, nargs, self)
  File ".../pypy/interpreter/baseobjspace.py", line 1015, in call_valuestack
    return w_func.funccall_valuestack(nargs, frame)
  File ".../pypy/interpreter/function.py", line 128, in funccall_valuestack
    return code.fastcall_0(self.space, self)
  File ".../pypy/interpreter/gateway.py", line 705, in fastcall_0
    self.handle_exception(space, e)
  File ".../pypy/interpreter/gateway.py", line 648, in handle_exception
    rstackovf.check_stack_overflow()
  File ".../pypy/interpreter/gateway.py", line 700, in fastcall_0
    w_result = self.fastfunc_0(space)
  File ".../pypy/module/posix/interp_posix.py", line 706, in fork
    run_fork_hooks('child', space)
  File ".../pypy/module/posix/interp_posix.py", line 690, in run_fork_hooks
    hook(space)
  File ".../pypy/rpython/lltypesystem/rffi.py", line 241, in wrapper
    res = call_external_function(*real_args)
  File "<6063-codegen .../pypy/rpython/lltypesystem/rffi.py:168>", line 6,
in call_external_function
  File ".../pypy/rpython/lltypesystem/lltype.py", line 1283, in __call__
    return callb(*args)
  File ".../pypy/rpython/lltypesystem/ll2ctypes.py", line 1164, in __call__
    cfunc = get_ctypes_callable(self.funcptr, self.calling_conv)
  File ".../pypy/rpython/lltypesystem/ll2ctypes.py", line 1138, in
get_ctypes_callable
    funcname, place))
NotImplementedError: function 'PyThread_ReInitTLS' not found in library
'/tmp/usession-default-21/module_cache/pypyapi.so'
"""

I have no clue why it thinks it needs to call that function. Any idea?

Stefan

_______________________________________________
pypy-dev mailing list
pypy-dev@python.org
http://mail.python.org/mailman/listinfo/pypy-dev

Reply via email to