All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hiro Yoshioka <lkml.hyoshiok@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Hiro Yoshioka <hyoshiok@miraclelinux.com>
Subject: [RFC] [PATCH] cache pollution aware __copy_from_user_ll()
Date: Sun, 14 Aug 2005 18:16:00 +0900	[thread overview]
Message-ID: <98df96d305081402164ce52f8@mail.gmail.com> (raw)

Hi,

The following is a patch to reduce a cache pollution
of __copy_from_user_ll().

When I run simple iozone benchmark to find a performance bottleneck of
the linux kernel, I found that __copy_from_user_ll() spent CPU cycle
most and it did many cache misses.

The following is profiled by oprofile.

Top 5 CPU cycle
CPU: P4 / Xeon, speed 2200.91 MHz (estimated)
Counted GLOBAL_POWER_EVENTS events (time during which processor is not
stopped) with a unit mask of 0x01 (mandatory) count 100000
samples  %        app name                 symbol name
281538   15.2083  vmlinux                  __copy_from_user_ll
81069     4.3792  vmlinux                  _spin_lock
75523     4.0796  vmlinux                  journal_add_journal_head
63674     3.4396  vmlinux                  do_get_write_access
52634     2.8432  vmlinux                  journal_put_journal_head
(pattern9-0-cpu4-0-08141700/summary.out)

Top 5 Memory Access and Cache miss
CPU: P4 / Xeon, speed 2200.91 MHz (estimated)
Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus
unit) with a unit mask of 0x3f (multiple flags) count 3000
Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus
unit) with a unit mask of 0x200 (read 3rd level cache miss) count 3000
samples  %        samples  %        app name                 symbol name
120801    7.4379  37017    63.4603  vmlinux                  __copy_from_user_ll
84139     5.1806  885       1.5172  vmlinux                  _spin_lock
66027     4.0654  656       1.1246  vmlinux                 
journal_add_journal_head
60400     3.7189  250       0.4286  vmlinux                  __find_get_block
60032     3.6963  120       0.2057  vmlinux                 
journal_dirty_metadata

__copy_from_user_ll spent 63.4603% of L3 cache miss though it spent only
7.4379% of memory access.

In order to reduce the cache miss in the __copy_from_user_ll, I made
the following patch and confirmed the reduction of the miss.

Top 5 CPU cycle
CPU: P4 / Xeon, speed 2200.93 MHz (estimated)
Counted GLOBAL_POWER_EVENTS events (time during which processor is not
stopped) with a unit mask of 0x01 (mandatory) count 100000
samples  %        app name                 symbol name
120717    8.3454  vmlinux                  _mmx_memcpy_nt
65955     4.5596  vmlinux                  do_get_write_access
56088     3.8775  vmlinux                  journal_put_journal_head
52550     3.6329  vmlinux                  journal_dirty_metadata
38886     2.6883  vmlinux                  journal_add_journal_head
pattern9-0-cpu4-0-08141627/summary.out

_mmx_memcpy_nt is the new function which is called from
__copy_from_user_ll and it spent only 42.88% of the original
implementation. (120717/281538==42.88%)

Top 5 Memory Access
CPU: P4 / Xeon, speed 2200.93 MHz (estimated)
Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus
unit) with a unit mask of 0x3f (multiple flags) count 3000
Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus
unit) with a unit mask of 0x200 (read 3rd level cache miss) count 3000
samples  %        samples  %        app name                 symbol name
90918     6.3079  89        0.5673  vmlinux                  _mmx_memcpy_nt
83654     5.8039  177       1.1283  vmlinux                 
journal_dirty_metadata
57836     4.0127  348       2.2183  vmlinux                 
journal_put_journal_head
48236     3.3466  165       1.0518  vmlinux                  do_get_write_access
44546     3.0906  21        0.1339  vmlinux                  __getblk

The cache miss reduced from 37017 (63.4603%) to 89 (0.5673%). It is
0.24% of the original implementation.

The actual elapse time which five times run  were 229.76 (sec) and
222.94 (sec). (229.76/222.94= 3.06% gain)

iozone -CMR -i 0 -+n -+u -s 8000MB -t 4 

What do you think?

--- linux-2.6.12.4.orig/arch/i386/lib/usercopy.c	2005-08-05
16:04:37.000000000 +0900
+++ linux-2.6.12.4/arch/i386/lib/usercopy.c	2005-08-12 13:18:14.106916200 +0900
@@ -10,6 +10,7 @@
  #include <linux/highmem.h>
  #include <linux/blkdev.h>
  #include <linux/module.h>
+#include <asm/i387.h>
  #include <asm/uaccess.h>
  #include <asm/mmx.h>
 
@@ -511,6 +512,108 @@
 		: "memory");						\
 } while (0)
 
+/* Non Temporal Hint version of mmx_memcpy */
+/* It is cache aware                       */
+/* hyoshiok@miraclelinux.com               */
+static unsigned long _mmx_memcpy_nt(void *to, const void *from, size_t len)
+{
+        /* Note! gcc doesn't seem to align stack variables properly, so we
+         * need to make use of unaligned loads and stores.
+         */
+	void *p;
+	int i;
+
+	if (unlikely(in_interrupt())){
+	        __copy_user_zeroing(to, from, len);
+		return len;
+	}
+
+	p = to;
+	i = len >> 6; /* len/64 */
+
+        kernel_fpu_begin();
+
+	__asm__ __volatile__ (
+		"1: prefetchnta (%0)\n"		/* This set is 28 bytes */
+		"   prefetchnta 64(%0)\n"
+		"   prefetchnta 128(%0)\n"
+		"   prefetchnta 192(%0)\n"
+		"   prefetchnta 256(%0)\n"
+		"2:  \n"
+		".section .fixup, \"ax\"\n"
+		"3: movw $0x1AEB, 1b\n"	/* jmp on 26 bytes */
+		"   jmp 2b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.align 4\n"
+		"	.long 1b, 3b\n"
+		".previous"
+		: : "r" (from) );
+		
+	for(; i>5; i--)
+	{
+		__asm__ __volatile__ (
+		"1:  prefetchnta 320(%0)\n"
+		"2:  movq (%0), %%mm0\n"
+		"  movq 8(%0), %%mm1\n"
+		"  movq 16(%0), %%mm2\n"
+		"  movq 24(%0), %%mm3\n"
+		"  movntq %%mm0, (%1)\n"
+		"  movntq %%mm1, 8(%1)\n"
+		"  movntq %%mm2, 16(%1)\n"
+		"  movntq %%mm3, 24(%1)\n"
+		"  movq 32(%0), %%mm0\n"
+		"  movq 40(%0), %%mm1\n"
+		"  movq 48(%0), %%mm2\n"
+		"  movq 56(%0), %%mm3\n"
+		"  movntq %%mm0, 32(%1)\n"
+		"  movntq %%mm1, 40(%1)\n"
+		"  movntq %%mm2, 48(%1)\n"
+		"  movntq %%mm3, 56(%1)\n"
+		".section .fixup, \"ax\"\n"
+		"3: movw $0x05EB, 1b\n"	/* jmp on 5 bytes */
+		"   jmp 2b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.align 4\n"
+		"	.long 1b, 3b\n"
+		".previous"
+		: : "r" (from), "r" (to) : "memory");
+		from+=64;
+		to+=64;
+	}
+
+	for(; i>0; i--)
+	{
+		__asm__ __volatile__ (
+		"  movq (%0), %%mm0\n"
+		"  movq 8(%0), %%mm1\n"
+		"  movq 16(%0), %%mm2\n"
+		"  movq 24(%0), %%mm3\n"
+		"  movntq %%mm0, (%1)\n"
+		"  movntq %%mm1, 8(%1)\n"
+		"  movntq %%mm2, 16(%1)\n"
+		"  movntq %%mm3, 24(%1)\n"
+		"  movq 32(%0), %%mm0\n"
+		"  movq 40(%0), %%mm1\n"
+		"  movq 48(%0), %%mm2\n"
+		"  movq 56(%0), %%mm3\n"
+		"  movntq %%mm0, 32(%1)\n"
+		"  movntq %%mm1, 40(%1)\n"
+		"  movntq %%mm2, 48(%1)\n"
+		"  movntq %%mm3, 56(%1)\n"
+		: : "r" (from), "r" (to) : "memory");
+		from+=64;
+		to+=64;
+	}
+	/*
+	 *	Now do the tail of the block
+	 */
+	kernel_fpu_end();
+	if(i=(len&63))
+	  __copy_user_zeroing(to, from, i);
+	return i;
+}
 
  unsigned long __copy_to_user_ll(void __user *to, const void *from,
unsigned long n)
 {
@@ -575,10 +678,14 @@
  __copy_from_user_ll(void *to, const void __user *from, unsigned long n)
 {
 	BUG_ON((long)n < 0);
-	if (movsl_is_ok(to, from, n))
+	if (n < 512) {
+	  if (movsl_is_ok(to, from, n))
 		__copy_user_zeroing(to, from, n);
-	else
+	  else
 		n = __copy_user_zeroing_intel(to, from, n);
+	}
+	else
+	  n = _mmx_memcpy_nt(to, from, n);
 	return n;
 }

Thanks in advance,
  Hiro
--
hyoshiok at miraclelinux.com

             reply	other threads:[~2005-08-14  9:16 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-08-14  9:16 Hiro Yoshioka [this message]
2005-08-14  9:41 ` [RFC] [PATCH] cache pollution aware __copy_from_user_ll() Arjan van de Ven
2005-08-14 10:22   ` Hiro Yoshioka
2005-08-14 10:35     ` Arjan van de Ven
2005-08-14 10:45       ` Christoph Hellwig
2005-08-15  6:43       ` Hiro Yoshioka
2005-08-15  7:16         ` Arjan van de Ven
2005-08-15  8:44           ` Hiro Yoshioka
2005-08-15  8:53             ` Arjan van de Ven
2005-08-15 23:33               ` Hiro Yoshioka
2005-08-16  3:30                 ` Hiro Yoshioka
2005-08-16  4:17                   ` Hirokazu Takahashi
2005-08-16  4:54                     ` Hiro Yoshioka
2005-08-16  5:43                       ` Arjan van de Ven
2005-08-16 10:16                         ` Hiro Yoshioka
2005-08-16 10:19                           ` Hirokazu Takahashi
2005-08-16 10:25                           ` Arjan van de Ven
2005-08-16 10:24                             ` Hirokazu Takahashi
2005-08-16  5:44                     ` Arjan van de Ven
2005-08-16  5:49                   ` Arjan van de Ven
     [not found]                     ` <20050817.110503.97359275.taka@valinux.co.jp>
2005-08-17  5:10                       ` Hiro Yoshioka
2005-08-17 14:30                         ` Akira Tsukamoto
2005-08-17 15:27                           ` Akira Tsukamoto
2005-08-18 17:53                             ` Lee Revell
2005-08-18  2:37                           ` Akira Tsukamoto
  -- strict thread matches above, loose matches on Subject: below --
2005-08-14 21:24 Ian Kumlien
2005-08-15  7:21 ` Arjan van de Ven
2005-08-15 14:49   ` Ian Kumlien
2005-08-15 12:15 linux
2005-08-15 12:25 ` Arjan van de Ven
     [not found] <20050815121555.29159.qmail@science.horizon.com.suse.lists.linux.kernel>
     [not found] ` <1124108702.3228.33.camel@laptopd505.fenrus.org.suse.lists.linux.kernel>
2005-08-15 15:02   ` Andi Kleen
2005-08-15 15:09     ` Arjan van de Ven
2005-08-15 15:13       ` Andi Kleen
     [not found] <20050816.131729.15816429.taka@valinux.co.jp.suse.lists.linux.kernel>
     [not found] ` <20050816.135425.719901536.hyoshiok@miraclelinux.com.suse.lists.linux.kernel>
     [not found]   ` <1124171015.3215.0.camel@laptopd505.fenrus.org.suse.lists.linux.kernel>
     [not found]     ` <20050816.191617.1025215458.hyoshiok@miraclelinux.com.suse.lists.linux.kernel>
     [not found]       ` <1124187950.3215.31.camel@laptopd505.fenrus.org.suse.lists.linux.kernel>
2005-08-16 13:15         ` Andi Kleen
2005-08-18 11:06           ` Hiro Yoshioka
2005-08-18 11:11             ` Hiro Yoshioka
2005-08-18 23:29               ` Hiro Yoshioka
2005-08-22  1:24                 ` Hiro Yoshioka
2005-08-22 13:07                   ` Andi Kleen
2005-08-22  2:43                 ` Hiro Yoshioka
2005-08-22 23:12                 ` Hiro Yoshioka
2005-08-24 14:11                   ` Hiro Yoshioka
2005-08-24 14:21                     ` Arjan van de Ven
2005-08-24 16:22                     ` Hirokazu Takahashi
2005-08-25  4:53                       ` Hiro Yoshioka
2005-08-16 18:09 Chuck Ebbert
2005-08-16 23:21 ` Hiro Yoshioka
2005-08-17  4:50   ` Hiro Yoshioka
2005-08-17 15:19 Chuck Ebbert
2005-08-18  9:45 ` Hiro Yoshioka
     [not found] <20050818.201138.607962419.hyoshiok@miraclelinux.com.suse.lists.linux.kernel>
     [not found] ` <98df96d30508181629d85edb5@mail.gmail.com.suse.lists.linux.kernel>
     [not found]   ` <20050823.081246.846946371.hyoshiok@miraclelinux.com.suse.lists.linux.kernel>
     [not found]     ` <20050824.231156.278740508.hyoshiok@miraclelinux.com.suse.lists.linux.kernel>
2005-08-24 16:18       ` Andi Kleen
2005-08-25  4:54         ` Hiro Yoshioka
2005-09-01  9:07           ` Hiro Yoshioka
2005-09-01  9:36             ` Andi Kleen
2005-09-02  1:43               ` Hiro Yoshioka
2005-09-02  2:06                 ` Andi Kleen
2005-09-02  2:08                 ` Andrew Morton
2005-09-02  2:17                   ` Andi Kleen
2005-09-02  2:28                     ` Andrew Morton
2005-09-02  3:41                       ` Hiro Yoshioka
2005-09-02  4:29             ` Andrew Morton
2005-09-02  4:37               ` Hiro Yoshioka
2005-09-03 11:59                 ` Hiro Yoshioka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=98df96d305081402164ce52f8@mail.gmail.com \
    --to=lkml.hyoshiok@gmail.com \
    --cc=hyoshiok@miraclelinux.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.