As far as an implementation of atomics on PPC goes, I recommend starting with GCC intrinsics, as these are also supported by IBM XLC. Leave inline assembly as an possible optimization later. I doubt it is worth the extra effort in most cases.
If someone wants to work on this, I can try to help with testing and such. I have access to both Blue Gene and POWER7 systems right now. I may be able to arrange access for Chapel developers if that is critical. Jeff Sent from my iPhone > On Nov 20, 2013, at 8:57 AM, "Michael P. Ferguson" <[email protected]> > wrote: > > Hi Jason - > > Can you explain why the existing atomics interface in > Atomics.chpl is not sufficient? > > Then, assuming you need some different functionality, why not extend > the existing atomics implementation instead of creating a completely > new one? The existing implementation defines functions like > atomic_fetch_add_explicit_uint_least64 > in runtime/include/atomics/*/chpl-atomics.h > > For example, to create XLC style Power intrinsics, it would make sense > to add a new directory there with a different .h file. > > You can call these C functions directly from Chapel, although I could > believe that you need to change something to get them to do what you > want. The Atomics module mostly adds an 'on' statement around these calls. > > Cheers, > > -michael > > ________________________________________ > From: Jason Riedy [[email protected]] > Sent: Tuesday, November 19, 2013 18:50 > To: [email protected] > Subject: Atomic-intrinsics.chpl sanity check > > [this is a bit of a follow-up to in-person interactions at SC13, > but posting it here for a wider audience (aka not pestering Brad > *again*)...] > > Does the following seem like a half-way sane method for adapting > to different compilers' intrinsics in Chapel? There's heavy > cheating around the ll/sc, and I don't have a Power account handy > for testing, so consider this a sketch... > > > // module Atomic-intrinsics.chpl > use Atomics; > > module impl { > use ChapelBase; > // XXX: Don't recall if pgi implements these... > inline proc gccish_intrinsics() param { > return CHPL_TARGET_COMPILER == "gnu" || CHPL_TARGET_COMPILER == "intel" || > CHPL_TARGET_COMPILER == "pgi" || CHPL_TARGET_COMPILER == > "cray-prgenv-gnu" || > CHPL_TARGET_COMPILER == "cray-prgenv-intel" || > CHPL_TARGET_COMPILER == "cray-prgenv-pgi"; > } > // XXX: This should be for xlc on power and not other platforms. > inline proc xlcish_power_intrinsics() param { > return CHPL_TARGET_COMPILER == "xlc"; > } > inline proc xmtish_intrinsics() param { > compilerError("Get a real machine."); > return false; > } > inline proc target_compiler_name() param { return CHPL_TARGET_COMPILER; } > } > use impl; > > > // local{} clauses just to make sure... > > // OP: add > > inline proc atomic_fetch_add(ref x, val: x.type, const > order:memory_order=memory_order_seq_cst) : x.type { > if (gccish_intrinsics()) { > extern proc __atomic_fetch_add(ref x: real(64), val: real(64), > order:memory_order) : real(64); > extern proc __atomic_fetch_add(ref x: int(64), val: int(64), > order:memory_order) : int(64); > extern proc __atomic_fetch_add(ref x: uint(64), val: uint(64), > order:memory_order) : uint(64); > extern proc __atomic_fetch_add(ref x: real(32), val: real(32), > order:memory_order) : real(32); > extern proc __atomic_fetch_add(ref x: int(32), val: int(32), > order:memory_order) : int(32); > extern proc __atomic_fetch_add(ref x: uint(32), val: uint(32), > order:memory_order) : uint(32); > extern proc __atomic_fetch_add(ref x: int(16), val: int(16), > order:memory_order) : int(16); > extern proc __atomic_fetch_add(ref x: uint(16), val: uint(16), > order:memory_order) : uint(16); > extern proc __atomic_fetch_add(ref x: int(8), val: int(8), > order:memory_order) : int(8); > extern proc __atomic_fetch_add(ref x: uint(8), val: uint(8), > order:memory_order) : uint(8); > inline proc __atomic_fetch_add(x, val, order) { > compilerError("No fetch and add for this type."); > return 0:x.type; > } > > var retval : x.type; > local { > retval = __atomic_fetch_add(x, val, order); > } > return retval; > } else if (xlcish_power_intrinsics()) { > compilerWarning("Completely untested atomics for ", > target_compiler_name()); > compilerWarning(" Needs isync, eieio, etc. for memory order."); > var retval : x.type; > inline proc __fa(ref x: int(32), in val: int(32)) { > extern proc __fetch_and_add(ref x: int(32), in val: int(32)) : int(32); > return __fetch_and_add(x, val); > } > inline proc __fa(ref x: int(64), in val: int(64)) { > extern proc __fetch_and_addlp(ref x: int(64), in val: int(64)) : int(64); > return __fetch_and_addlp(x, val); > } > inline proc __fa(ref x: real(32), in val: real(32)) { > extern proc __lwarx(ref x: real(32)) : real(32); > extern proc __stwcx(ref x: real(32), in val: real(32)) : int(32); > var outval : real(32); > var newval : real(32); > do { > outval = __lwarx(x); > newval = outval + val; > } while !(__stwcx (x, newval)); > return outval; > } > inline proc __fa(ref x: real(64), in val: real(64)) { > extern proc __ldarx(ref x: real(64)) : real(64); > extern proc __stdcx(ref x: real(64), in val: real(64)) : int(64); > var outval : real(64); > var newval : real(64); > do { > outval = __ldarx(x); > newval = outval + val; > } while !(__stdcx (x, newval)); > return outval; > } > inline proc __fa(x, val) { > compilerError("No fetch and add for this type."); > } > local { > retval = __fa(x, val); > } > return retval; > } else { > compilerError("Unrecognized target compiler: ", target_compiler_name()); > } > } > > inline proc atomic_add_fetch(ref x, val: x.type, const > order:memory_order=memory_order_seq_cst) : x.type { > if (gccish_intrinsics()) { > extern proc __atomic_add_fetch(ref x: real(64), val: real(64), > order:memory_order) : real(64); > extern proc __atomic_add_fetch(ref x: int(64), val: int(64), > order:memory_order) : int(64); > extern proc __atomic_add_fetch(ref x: uint(64), val: uint(64), > order:memory_order) : uint(64); > extern proc __atomic_add_fetch(ref x: real(32), val: real(32), > order:memory_order) : real(32); > extern proc __atomic_add_fetch(ref x: int(32), val: int(32), > order:memory_order) : int(32); > extern proc __atomic_add_fetch(ref x: uint(32), val: uint(32), > order:memory_order) : uint(32); > extern proc __atomic_add_fetch(ref x: int(16), val: int(16), > order:memory_order) : int(16); > extern proc __atomic_add_fetch(ref x: uint(16), val: uint(16), > order:memory_order) : uint(16); > extern proc __atomic_add_fetch(ref x: int(8), val: int(8), > order:memory_order) : int(8); > extern proc __atomic_add_fetch(ref x: uint(8), val: uint(8), > order:memory_order) : uint(8); > inline proc __atomic_add_fetch(x, val, order) { > compilerError("No fetch and add for this type."); > return 0:x.type; > } > > var retval : x.type; > local { > retval = __atomic_add_fetch(x, val, order); > } > return retval; > } else if (xlcish_power_intrinsics()) { > compilerWarning("Completely untested atomics for ", > target_compiler_name()); > compilerWarning(" Needs isync, eieio, etc. for memory order."); > var retval : x.type; > inline proc __fa(ref x: int(32), in val: int(32)) { > extern proc __fetch_and_add(ref x: int(32), in val: int(32)) : int(32); > return __fetch_and_add(x, val) + val; > } > inline proc __fa(ref x: int(64), in val: int(64)) { > extern proc __fetch_and_addlp(ref x: int(64), in val: int(64)) : int(64); > return __fetch_and_addlp(x, val) + val; > } > inline proc __fa(ref x: real(32), in val: real(32)) { > extern proc __lwarx(ref x: real(32)) : real(32); > extern proc __stwcx(ref x: real(32), in val: real(32)) : int(32); > var outval : real(32); > var newval : real(32); > do { > outval = __lwarx(x); > newval = outval + val; > } while !(__stwcx (x, newval)); > return newval; > } > inline proc __fa(ref x: real(64), in val: real(64)) { > extern proc __ldarx(ref x: real(64)) : real(64); > extern proc __stdcx(ref x: real(64), in val: real(64)) : int(64); > var outval : real(64); > var newval : real(64); > do { > outval = __ldarx(x); > newval = outval + val; > } while !(__stdcx (x, newval)); > return newval; > } > inline proc __fa(x, val) { > compilerError("No fetch and add for this type."); > } > local { > retval = __fa(x, val); > } > return retval; > } else { > compilerError("Unrecognized target compiler: ", target_compiler_name()); > } > } > > > inline proc atomic_add(ref x, val: x.type, const > order:memory_order=memory_order_seq_cst) : x.type { > // Sufficient. > return atomic_fetch_add(x, val, order); > } > > -- > Jason Riedy > > > ------------------------------------------------------------------------------ > Shape the Mobile Experience: Free Subscription > Software experts and developers: Be at the forefront of tech innovation. > Intel(R) Software Adrenaline delivers strategic insight and game-changing > conversations that shape the rapidly evolving mobile landscape. Sign up now. > http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk > _______________________________________________ > Chapel-users mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/chapel-users > > ------------------------------------------------------------------------------ > Shape the Mobile Experience: Free Subscription > Software experts and developers: Be at the forefront of tech innovation. > Intel(R) Software Adrenaline delivers strategic insight and game-changing > conversations that shape the rapidly evolving mobile landscape. Sign up now. > http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk > _______________________________________________ > Chapel-users mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/chapel-users ------------------------------------------------------------------------------ Shape the Mobile Experience: Free Subscription Software experts and developers: Be at the forefront of tech innovation. Intel(R) Software Adrenaline delivers strategic insight and game-changing conversations that shape the rapidly evolving mobile landscape. Sign up now. http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk _______________________________________________ Chapel-users mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/chapel-users
