On Fri, Aug 18, 2023 at 11:18:19AM +0800, Zhu, Lipeng wrote:
> From: Lipeng Zhu <lipeng....@intel.com>
> 
> This patch try to introduce the rwlock and split the read/write to
> unit_root tree and unit_cache with rwlock instead of the mutex to
> increase CPU efficiency. In the get_gfc_unit function, the percentage
> to step into the insert_unit function is around 30%, in most instances,
> we can get the unit in the phase of reading the unit_cache or unit_root
> tree. So split the read/write phase by rwlock would be an approach to
> make it more parallel.
> 
> BTW, the IPC metrics can gain around 9x in our test
> server with 220 cores. The benchmark we used is
> https://github.com/rwesson/NEAT
> 
> libgcc/ChangeLog:
> 
>     * gthr-posix.h (__GTHREAD_RWLOCK_INIT): New macro
>     (__gthrw): New function
>     (__gthread_rwlock_rdlock): New function
>     (__gthread_rwlock_tryrdlock): New function
>     (__gthread_rwlock_wrlock): New function
>     (__gthread_rwlock_trywrlock): New function
>     (__gthread_rwlock_unlock): New function
> 
> libgfortran/ChangeLog:
> 
>     * io/async.c (DEBUG_LINE): New
>     * io/async.h (RWLOCK_DEBUG_ADD): New macro
>     (CHECK_RDLOCK): New macro
>     (CHECK_WRLOCK): New macro
>     (TAIL_RWLOCK_DEBUG_QUEUE): New macro
>     (IN_RWLOCK_DEBUG_QUEUE): New macro
>     (RDLOCK): New macro
>     (WRLOCK): New macro
>     (RWUNLOCK): New macro
>     (RD_TO_WRLOCK): New macro
>     (INTERN_RDLOCK): New macro
>     (INTERN_WRLOCK): New macro
>     (INTERN_RWUNLOCK): New macro
>     * io/io.h (internal_proto): Define unit_rwlock
>     * io/transfer.c (st_read_done_worker): Relace unit_lock with unit_rwlock
>     (st_write_done_worker): Relace unit_lock with unit_rwlock
>     * io/unit.c (get_gfc_unit): Relace unit_lock with unit_rwlock
>     (if): Relace unit_lock with unit_rwlock
>     (close_unit_1): Relace unit_lock with unit_rwlock
>     (close_units): Relace unit_lock with unit_rwlock
>     (newunit_alloc): Relace unit_lock with unit_rwlock
>     * io/unix.c (flush_all_units): Relace unit_lock with unit_rwlock

The changeLog entries are all incorrect.
1) they should be indented by a tab, not 4 spaces, and should end with
   a dot
2) when several consecutive descriptions have the same text, especially
   when it is long, it should use Likewise. for the 2nd and following
3) (internal_proto) is certainly not what you've changed, from what I can
   see in io.h you've done:
        * io/io.h (struct gfc_unit): Change UNIT_LOCK to UNIT_RWLOCK in
        a comment.
        (unit_lock): Remove including associated internal_proto.
        (unit_rwlock): New declarations including associated internal_proto.
        (dec_waiting_unlocked): Use WRLOCK and RWUNLOCK on unit_rwlock
        instead of __gthread_mutex_lock and __gthread_mutex_unlock on
        unit_lock.
   (if) is certainly not what you've changed either, always find what
   function or macro the change was in, or if you remove something, state
   it, if you add something, state it.
4) all the
   Replace unit_lock with unit_rwlock. descriptions only partially match
   reality, you've also changed the operations on those variables.

> --- a/libgfortran/io/async.h
> +++ b/libgfortran/io/async.h
> @@ -207,9 +207,132 @@
>      INTERN_LOCK (&debug_queue_lock);                                 \
>      MUTEX_DEBUG_ADD (mutex);                                         \
>      INTERN_UNLOCK (&debug_queue_lock);                                       
> \
> -    DEBUG_PRINTF ("%s" DEBUG_RED "ACQ:" DEBUG_NORM " %-30s %78p\n", 
> aio_prefix, #mutex, mutex); \
> +    DEBUG_PRINTF ("%s" DEBUG_RED "ACQ:" DEBUG_NORM " %-30s %78p\n", 
> aio_prefix, #mutex, \
> +              mutex); \

Why are you changing this at all?

> +#define RD_TO_WRLOCK(rwlock) \
> +  RWUNLOCK (rwlock);\

At least a space before \ (or better tab

> +#define RD_TO_WRLOCK(rwlock) \
> +  RWUNLOCK (rwlock);\

Likewise.

> +  WRLOCK (rwlock);
> +#endif
> +#endif
> +
> +#ifndef __GTHREAD_RWLOCK_INIT
> +#define RDLOCK(rwlock) LOCK (rwlock)
> +#define WRLOCK(rwlock) LOCK (rwlock)
> +#define RWUNLOCK(rwlock) UNLOCK (rwlock)
> +#define RD_TO_WRLOCK(rwlock) {}

do {} while (0)
instead of {}
?

>  #endif
>  
>  #define INTERN_LOCK(mutex) T_ERROR (__gthread_mutex_lock, mutex);
>  
>  #define INTERN_UNLOCK(mutex) T_ERROR (__gthread_mutex_unlock, mutex);
>  
> +#define INTERN_RDLOCK(rwlock) T_ERROR (__gthread_rwlock_rdlock, rwlock);
> +#define INTERN_WRLOCK(rwlock) T_ERROR (__gthread_rwlock_wrlock, rwlock);
> +#define INTERN_RWUNLOCK(rwlock) T_ERROR (__gthread_rwlock_unlock, rwlock);

Admittedly preexisting issue, but I wonder why the ; at the end, all the
uses of RDLOCK etc. I've seen were followed by ;

> --- a/libgfortran/io/unit.c
> +++ b/libgfortran/io/unit.c
> @@ -33,34 +33,36 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
> If not, see
>  
>  
>  /* IO locking rules:
> -   UNIT_LOCK is a master lock, protecting UNIT_ROOT tree and UNIT_CACHE.
> +   UNIT_RWLOCK is a master lock, protecting UNIT_ROOT tree and UNIT_CACHE.

master rw lock
?

> +/* get_gfc_unit_from_root()-- Given an integer, return a pointer
> +  to the unit structure. Returns NULL if the unit does not exist,
> +   otherwise returns a locked unit. */

Formatting, to is indented differently from otherwise, both should
be 3 spaces, and there should be 2 spaces after ., rather than just
one (in both spots).

> +
> +static inline gfc_unit * get_gfc_unit_from_unit_root (int n)

Formatting, there shouldn't be space after *, but also function
name should be at the beginning of line, so in this case it should
be
static inline gfc_unit *
get_gfc_unit_from_unit_root (int n)

> +{
> +    gfc_unit *p;
> +    int c = 0;
> +    p = unit_root;

This should be indented by 2 spaces rather than 4.

> +  while (p != NULL)
> +    {
> +      c = compare (n, p->unit_number);
> +      if (c < 0)
> +     p = p->left;
> +      if (c > 0)
> +     p = p->right;
> +      if (c == 0)
> +     break;
> +    }
> +    return p;

And the above return p; line as well.

        Jakub

Reply via email to