LINUX.ORG.RU

Новая оптимизация функции memset() в glibc

 , , ,


0

2

Инженер из Intel, Ноах Голдштейн, оптимизировал функцию memset() в библиотеке glibc. Данная оптимизация даёт прирост в производительности порядка 7.5% на десктопных версиях процессоров архитектур Skylake-X и Ice Lake. У серверных версий прирост в производительности немного ниже, прежде всего из-за более низкой общей производительности одиночного ядра.

В прежней реализации функции memset() использовалась ассемблерная инструкция rep stosb. До недавнего времени эта инструкция работала достаточно быстро, за счёт внутрипроцессорной оптимизации zero-over-zero writeback. Однако в этой оптимизации была найдена потенциальная уязвимость, которая может привести к атаке по побочному каналу. В результате оптимизация zero-over-zero writeback была отменена, что и привело к ухудшению производительности rep stosb. В новой версии memset() инструкция rep stosb всё ещё используется, но при выполнении более строгих условий.

Что именно изменилось, можно понять по изменению следующего комментария в коде, который описывает подробности реализации memset()

Прежняя версия описания:

/* memset is implemented as:
   1. Use overlapping store to avoid branch.
   2. If size is less than VEC, use integer register stores.
   3. If size is from VEC_SIZE to 2 * VEC_SIZE, use 2 VEC stores.
   4. If size is from 2 * VEC_SIZE to 4 * VEC_SIZE, use 4 VEC stores.
   5. On machines ERMS feature, if size is greater or equal than
      __x86_rep_stosb_threshold then REP STOSB will be used.
   6. If size is more to 4 * VEC_SIZE, align to 4 * VEC_SIZE with
      4 VEC stores and store 4 * VEC at a time until done.  */

Новая версия описания:

/* memset is implemented as:
   1. Use overlapping store to avoid branch.
   2. If size is less than VEC, use integer register stores.
   3. If size is from VEC_SIZE to 2 * VEC_SIZE, use 2 VEC stores.
   4. If size is from 2 * VEC_SIZE to 4 * VEC_SIZE, use 4 VEC stores.
   5. If size is more to 4 * VEC_SIZE, align to 1 * VEC_SIZE with
      4 VEC stores and store 4 * VEC at a time until done.
   6. On machines ERMS feature, if size is range
	  [__x86_rep_stosb_threshold, __x86_memset_non_temporal_threshold)
	  then REP STOSB will be used.
   7. If size >= __x86_memset_non_temporal_threshold, use a
	  non-temporal stores.  */

>>> Подробности



Проверено: Zhbert ()
Последнее исправление: Wizard_ (всего исправлений: 2)

Переносимость на другие архитектуры процессоров не страдает от таких ассемблерных вставок?

Infra_HDC ★★★★★
()

Патч:

diff --git a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
index 97839a2248..637caadb40 100644
--- a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
+++ b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S
@@ -21,10 +21,13 @@
    2. If size is less than VEC, use integer register stores.
    3. If size is from VEC_SIZE to 2 * VEC_SIZE, use 2 VEC stores.
    4. If size is from 2 * VEC_SIZE to 4 * VEC_SIZE, use 4 VEC stores.
-   5. On machines ERMS feature, if size is greater or equal than
-      __x86_rep_stosb_threshold then REP STOSB will be used.
-   6. If size is more to 4 * VEC_SIZE, align to 4 * VEC_SIZE with
-      4 VEC stores and store 4 * VEC at a time until done.  */
+   5. If size is more to 4 * VEC_SIZE, align to 1 * VEC_SIZE with
+      4 VEC stores and store 4 * VEC at a time until done.
+   6. On machines ERMS feature, if size is range
+	  [__x86_rep_stosb_threshold, __x86_shared_non_temporal_threshold)
+	  then REP STOSB will be used.
+   7. If size >= __x86_shared_non_temporal_threshold, use a
+	  non-temporal stores.  */
 
 #include <sysdep.h>
 
@@ -147,6 +150,41 @@ L(entry_from_wmemset):
 	VMOVU	%VMM(0), -VEC_SIZE(%rdi,%rdx)
 	VMOVU	%VMM(0), (%rdi)
 	VZEROUPPER_RETURN
+
+	/* If have AVX512 mask instructions put L(less_vec) close to
+	   entry as it doesn't take much space and is likely a hot target.  */
+#ifdef USE_LESS_VEC_MASK_STORE
+    /* Align to ensure the L(less_vec) logic all fits in 1x cache lines.  */
+	.p2align 6,, 47
+	.p2align 4
+L(less_vec):
+L(less_vec_from_wmemset):
+	/* Less than 1 VEC.  */
+# if VEC_SIZE != 16 && VEC_SIZE != 32 && VEC_SIZE != 64
+#  error Unsupported VEC_SIZE!
+# endif
+	/* Clear high bits from edi. Only keeping bits relevant to page
+	   cross check. Note that we are using rax which is set in
+	   MEMSET_VDUP_TO_VEC0_AND_SET_RETURN as ptr from here on out.  */
+	andl	$(PAGE_SIZE - 1), %edi
+	/* Check if VEC_SIZE store cross page. Mask stores suffer
+	   serious performance degradation when it has to fault suppress.  */
+	cmpl	$(PAGE_SIZE - VEC_SIZE), %edi
+	/* This is generally considered a cold target.  */
+	ja	L(cross_page)
+# if VEC_SIZE > 32
+	movq	$-1, %rcx
+	bzhiq	%rdx, %rcx, %rcx
+	kmovq	%rcx, %k1
+# else
+	movl	$-1, %ecx
+	bzhil	%edx, %ecx, %ecx
+	kmovd	%ecx, %k1
+# endif
+	vmovdqu8 %VMM(0), (%rax){%k1}
+	VZEROUPPER_RETURN
+#endif
+
 #if defined USE_MULTIARCH && IS_IN (libc)
 END (MEMSET_SYMBOL (__memset, unaligned))
 
@@ -185,54 +223,6 @@ L(last_2x_vec):
 #endif
 	VZEROUPPER_RETURN
 
-	/* If have AVX512 mask instructions put L(less_vec) close to
-	   entry as it doesn't take much space and is likely a hot target.
-	 */
-#ifdef USE_LESS_VEC_MASK_STORE
-	.p2align 4,, 10
-L(less_vec):
-L(less_vec_from_wmemset):
-	/* Less than 1 VEC.  */
-# if VEC_SIZE != 16 && VEC_SIZE != 32 && VEC_SIZE != 64
-#  error Unsupported VEC_SIZE!
-# endif
-	/* Clear high bits from edi. Only keeping bits relevant to page
-	   cross check. Note that we are using rax which is set in
-	   MEMSET_VDUP_TO_VEC0_AND_SET_RETURN as ptr from here on out.  */
-	andl	$(PAGE_SIZE - 1), %edi
-	/* Check if VEC_SIZE store cross page. Mask stores suffer
-	   serious performance degradation when it has to fault suppress.
-	 */
-	cmpl	$(PAGE_SIZE - VEC_SIZE), %edi
-	/* This is generally considered a cold target.  */
-	ja	L(cross_page)
-# if VEC_SIZE > 32
-	movq	$-1, %rcx
-	bzhiq	%rdx, %rcx, %rcx
-	kmovq	%rcx, %k1
-# else
-	movl	$-1, %ecx
-	bzhil	%edx, %ecx, %ecx
-	kmovd	%ecx, %k1
-# endif
-	vmovdqu8 %VMM(0), (%rax){%k1}
-	VZEROUPPER_RETURN
-
-# if defined USE_MULTIARCH && IS_IN (libc)
-	/* Include L(stosb_local) here if including L(less_vec) between
-	   L(stosb_more_2x_vec) and ENTRY. This is to cache align the
-	   L(stosb_more_2x_vec) target.  */
-	.p2align 4,, 10
-L(stosb_local):
-	movzbl	%sil, %eax
-	mov	%RDX_LP, %RCX_LP
-	mov	%RDI_LP, %RDX_LP
-	rep	stosb
-	mov	%RDX_LP, %RAX_LP
-	VZEROUPPER_RETURN
-# endif
-#endif
-
 #if defined USE_MULTIARCH && IS_IN (libc)
 	.p2align 4
 L(stosb_more_2x_vec):
@@ -318,21 +308,33 @@ L(return_vzeroupper):
 	ret
 #endif
 
-	.p2align 4,, 10
-#ifndef USE_LESS_VEC_MASK_STORE
-# if defined USE_MULTIARCH && IS_IN (libc)
+#ifdef USE_WITH_AVX2
+	.p2align 4
+#else
+	.p2align 4,, 4
+#endif
+
+#if defined USE_MULTIARCH && IS_IN (libc)
 	/* If no USE_LESS_VEC_MASK put L(stosb_local) here. Will be in
 	   range for 2-byte jump encoding.  */
 L(stosb_local):
+	cmp	__x86_shared_non_temporal_threshold(%rip), %RDX_LP
+	jae	L(nt_memset)
 	movzbl	%sil, %eax
 	mov	%RDX_LP, %RCX_LP
 	mov	%RDI_LP, %RDX_LP
 	rep	stosb
+# if (defined USE_WITH_SSE2) || (defined USE_WITH_AVX512)
+	/* Use xchg to save 1-byte (this helps align targets below).  */
+	xchg	%RDX_LP, %RAX_LP
+# else
 	mov	%RDX_LP, %RAX_LP
-	VZEROUPPER_RETURN
 # endif
+	VZEROUPPER_RETURN
+#endif
+#ifndef USE_LESS_VEC_MASK_STORE
 	/* Define L(less_vec) only if not otherwise defined.  */
-	.p2align 4
+	.p2align 4,, 12
 L(less_vec):
 	/* Broadcast esi to partial register (i.e VEC_SIZE == 32 broadcast to
 	   xmm). This is only does anything for AVX2.  */
@@ -423,4 +425,35 @@ L(between_2_3):
 	movb	%SET_REG8, -1(%LESS_VEC_REG, %rdx)
 #endif
 	ret
-END (MEMSET_SYMBOL (__memset, unaligned_erms))
+
+#if defined USE_MULTIARCH && IS_IN (libc)
+# ifdef USE_WITH_AVX512
+	/* Force align so the loop doesn't cross a cache-line.  */
+	.p2align 4
+# endif
+	.p2align 4,, 7
+    /* Memset using non-temporal stores.  */
+L(nt_memset):
+	VMOVU	%VMM(0), (VEC_SIZE * 0)(%rdi)
+	leaq	(VEC_SIZE * -4)(%rdi, %rdx), %rdx
+    /* Align DST.  */
+	orq	$(VEC_SIZE * 1 - 1), %rdi
+	incq	%rdi
+	.p2align 4,, 7
+L(nt_loop):
+	VMOVNT	%VMM(0), (VEC_SIZE * 0)(%rdi)
+	VMOVNT	%VMM(0), (VEC_SIZE * 1)(%rdi)
+	VMOVNT	%VMM(0), (VEC_SIZE * 2)(%rdi)
+	VMOVNT	%VMM(0), (VEC_SIZE * 3)(%rdi)
+	subq	$(VEC_SIZE * -4), %rdi
+	cmpq	%rdx, %rdi
+	jb	L(nt_loop)
+	sfence
+	VMOVU	%VMM(0), (VEC_SIZE * 0)(%rdx)
+	VMOVU	%VMM(0), (VEC_SIZE * 1)(%rdx)
+	VMOVU	%VMM(0), (VEC_SIZE * 2)(%rdx)
+	VMOVU	%VMM(0), (VEC_SIZE * 3)(%rdx)
+	VZEROUPPER_RETURN
+#endif
+
+END(MEMSET_SYMBOL(__memset, unaligned_erms))
dataman ★★★★★
()

жду создания «прогрессивной» ветки ядра и дистрибутива.

mrjaggers
()
Ответ на: комментарий от zg

Так как у меня написано.

Нет, не так. Даже если этот голдштейн из израильского офиса интела, а не американец в дцатом поколении, то его имя пишется в соответствии с правилами передачи еврейских имён в русском языке. К примеру:

русское написаниеивриттранскрипция иврита на русском
НоаנועהНо́а
НойנחНо́ах

Если ты правильно выбрал ютуб, то чувака по-русски зовут «Ной».

LamerOk ★★★★★
()
Ответ на: комментарий от zg

Переводом это было бы, если бы было написано ««успокаивающий», «умиротворяющий»». А то что выше - правила написания, умник.

PPP328 ★★★★★
()
Ответ на: комментарий от zg

Имена не переводятся.

Это ты не переводишься из третьего класса в четвёртый за двойку по русскому языку.

LamerOk ★★★★★
()
Ответ на: комментарий от PPP328

У человека есть его имя. Оно записывается именно так как звучит или фонетически наиболее близко к языку написания. Если бы его звали Йоханан, ты бы сказал, что по-русски нужно писать Иван? Разумеется нет.

Я может быть и умник, зато ты невежда. Такие как ты в HttpStatus.SC_NOT_FOUND тоже имена людям коверкают.

zg
() автор топика
Ответ на: комментарий от LamerOk

Кто бы говорил. Есть такое имя Алехандро - испанская форма имени Александр. Наверное в твоём классе для особо одарённых упорно пишут только Александр, даже когда человека так не зовут.

zg
() автор топика
Ответ на: комментарий от LamerOk

А если он американец - то его имя передаётся в соответствии с правилами для английских имён. Т.е. Ноа. Как, например, Gabriel будет Гэбриэлом, а не Гавриилом. И не Габриэлем (даже если он потомственный бруклинский еврей) - если только носитель имени сам не настаивает на последнем произношении.

IRASoldier ★★
()
Ответ на: комментарий от gns

Не в традиции дело. Царь Соломон известен из религиозных текстов, которые переводились в тёмные века всеобщей безграмотности и по цепочке языков, в некоторых из которых нет звука Ш. Например в греческом. Но если речь идёт о ныне живущем человеке по имени Шломо, то и по-русски его имя записывается и произносится именно Шломо и никак иначе. Вот для примера https://ru.wikipedia.org/wiki/%D0%90%D1%80%D1%86%D0%B8,_%D0%A8%D0%BB%D0%BE%D0%BC%D0%BE

zg
() автор топика
Ответ на: комментарий от gns

А его так и называют по-русски, когда о Соломоне речь не в православном или литературном контексте. Если ты говоришь о нем в контексте обсуждения иудаистской традиции, истории Израиля - ты говоришь о Шломо бен Давиде.

IRASoldier ★★
()
Ответ на: комментарий от zg

Мне как-то один любитель локализации доказывал на Опеннете, что поскольку латинские буквы «не принадлежат англосаксам», то и по-русски написанное такими буквами английское слово или аббревиатуру надлежит читать исключительно без оглядки на англоязычные особенности :-)

IRASoldier ★★
()
Ответ на: комментарий от IRASoldier

А если он американец - то его имя передаётся в соответствии с правилами для английских имён.

Многие просто не знают как правильно транслитерировать свои имена на английском. Поэтому Давид превращается в Дейвида, Дана в Дейну и так далее. Если бы вместо Dana записывали Danna, то никаких Дейн не было бы. При этом если человек приехал в Израиль из Америки и там его звали Дейвидом, то его и в Израиле продолжают так называть и записывать. Именно потому, что имена людей не переводятся. Переводятся лишь имена холопов.

zg
() автор топика
Последнее исправление: zg (всего исправлений: 1)
Ответ на: комментарий от IRASoldier

Мне как-то один любитель локализации доказывал на Опеннете, что поскольку латинские буквы «не принадлежат англосаксам», то и по-русски написанное такими буквами английское слово или аббревиатуру надлежит читать исключительно без оглядки на англоязычные особенности :-)

Ну как немка Екатерина Великая и прочие «русские» немцы вроде Эйлера русский народ научили, так до сих пор и говорят. Все эти «аш-тэ-тэ-пэ» и прочие «гэ-це-це» - это просто зашквар, но что поделаешь?

zg
() автор топика
Ответ на: комментарий от PPP328

Ты даже с переводом значения ошибся, зато поучаешь.

zg
() автор топика
Ответ на: комментарий от dataman

А другие не отличают фонетическую транскрипцию от практической.

Чисто практически человек просто не откликнется, если ты вместо Ноах обратишься к нему по имени Ной. Ной - это вообще другое имя, причём женское.

zg
() автор топика

А если вернуться к новости, то следует добавить, что данная оптимизация не единственная, которую сделал Ноах Голдштейн в glibc. Недавно было ещё несколько. Так что, любители роллинг дистрибутивов, приготовтесь к тестритованию. :-))

zg
() автор топика
Ответ на: комментарий от IRASoldier

Только как-то вот вспоминается недавняя дискуссия о том, как называть нового короля Великобритании — Карл или Чарльз? Да и бесконечные французские Луи даже не подозревали о том, что в России они станут Людовиками.

gns ★★★★★
()
Последнее исправление: gns (всего исправлений: 1)
Ответ на: комментарий от gns

Так вопрос риторический, и так понятно как. Так же и с Чарльзом, который стал Карлом, на немецкий манер, по имеющейся у них там в Великобритании традиции.

zg
() автор топика
Ответ на: комментарий от Infra_HDC

Переносимость на другие архитектуры процессоров не страдает от таких ассемблерных вставок?

А должна?

windows10 ★★★★★
()
Ответ на: комментарий от Infra_HDC

На других архитектурах свои ассемблерные вставки.

gns ★★★★★
()
Ответ на: комментарий от zg

Так же и с Чарльзом, который стал Карлом, на немецкий манер, по имеющейся у них там в Великобритании традиции.

У них там в Великобритании он остался Charles III. Это на русский переводится как Карл.

И некий Noah J. Goldstein официально переводится как Ноа (а не Ноах и не Ной!) Гольдштейн: https://readly.ru/author/1830/.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от LamerOk

то его имя пишется в соответствии с правилами передачи еврейских имён в русском языке

Если переводится Библия, то да.

А если переводится глава Торы, то она называется Ноах и повествует о Ноахе и его сыновьях Шеме, Хаме и Йофете.

monk ★★★★★
()
Ответ на: комментарий от zg

неа, это традиция русской культуры называть аглицких королей на немецкий манер. немчины много было в дореволюционной россии.
а в обыденной жизни как кому хочется.

pfg ★★★★★
()
Ответ на: комментарий от monk

Если переводится Библия, то да.
А если переводится глава Торы,

А ты зачем включил дурака? Ты тоже не знаешь про правила передачи имён собственных при переводе?

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Ещё раз, зависит от того, что переводим.

Периодически из-за этого случаются казусы: ФуджиФилм названа в честь Фудзиямы, баптисты называются в честь Иоанна Крестителя (он John the Baptist), Генри Гудзон и миссис Хадсон однофамильцы.

P.S. А если речь о переводе художественной литературы, так можно вспомнить Бильбо Торбинса/Сумкинса/Бэггинса.

monk ★★★★★
()
Ответ на: комментарий от MoldAndLimeHoney

По-русски это будет Ной, в крайнем случае Ноа.

Однако при переводе Торы не так. Хотя здесь логичнее всего Ноа. Также как в https://readly.ru/author/1830/

monk ★★★★★
()
Ответ на: комментарий от monk

Ещё раз, зависит от того, что переводим.

Мы переводим голдштейна. Наш голдштейн из библии или из торы? Если он ни оттуда, ни оттуда, то за каким хером ты их приплёл?

LamerOk ★★★★★
()
Ответ на: комментарий от pfg

:) имена культурно модифицируются под конкретный язык. Moscow, Пекин, Греция…

Это не имена, а названия.

zg
() автор топика
Ответ на: комментарий от zg

Ну пусть будут Гиммлер, Вашингтон и Елизавета 2.

monk ★★★★★
()
Ответ на: комментарий от monk

Мы переводим голдштейна

Я же написал.

Если переводится Библия, то да.
А если переводится глава Торы,

Ты себя хорошо чувствуешь? Голова не кружится? Спал нормально? Воду пьёшь?

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

А за каким хером ты приплёл правила перевода библейских еврейских имён?

John Connor у тебя будет Иоанн Коннор? Ведь יוחנן переводится как Иоанн.

monk ★★★★★
()
Ответ на: комментарий от monk

Но я вообще нигде в треде не упоминал перевода библейских имён. Ни еврейских, ни каких-либо других.

Я говорил про правила передачи имён. Правила русского языка. Передачи имён. В том числе - современных имён с современных иностранных языков. Включая правила передачи современных еврейских имён на современный русский язык.

А уж откуда пошли эти правила - от библии, фигиблии, торы или глиняных табличек - это вообще фиолетово.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Я говорил про правила передачи имён. Правила русского языка.

Утверждённые Институтом Русского Языка? Можно ссылку?

Включая правила передачи современных еврейских имён на современный русский язык.

Мы переводим Noah Goldstein. Ты настаиваешь, что надо для имени Noah применять правила для еврейского языка для имени נח. Тогда при переводе имени John Connor надо брать из той же таблички правило для имени יוחנן. Такая у тебя логика?

monk ★★★★★
()
Ответ на: комментарий от MoldAndLimeHoney

По-русски это будет Ной, в крайнем случае Ноа.

Какая ещё Ноа? Ноа - это уже второе другое имя и снова женское. Вы тут совсем с дуба рухнули или как? Вот представится вам обратиться к этому человеку в реале, вы его будете упорно звать Ной и Ноа, а когда он не отзовётся, обидетесь? Представь, что тебя самого родители назвали Ноах и вот, тебя уже 40+ лет так зовут, а тут какой-то иностранец обращается к тебе иначе, по совершенно другому имени, да ещё женскому.

zg
() автор топика
Последнее исправление: zg (всего исправлений: 1)
Ответ на: комментарий от zg

Какая ещё Ноа?

Попустись, дурачок. Если твой голдштейн из США / Британии, то его правильный перевод имени будет именно «Ноа».

LamerOk ★★★★★
()
Ответ на: комментарий от monk

Я говорил про правила передачи имён. Правила русского языка.

Утверждённые Институтом Русского Языка?

Вопросами перевода занимаются институты иностранных языков.

Можно ссылку?

Конкретно тебе (как и половине этого треда) нужна вот эта ссылка

Пункты указаны в порядке простоты объяснения, но сначала имя проверяется на наличие традиции передачи, и только в случае её отсутствия происходит переход на другие пункты алгоритма.

LamerOk ★★★★★
()
Последнее исправление: LamerOk (всего исправлений: 1)
Ответ на: комментарий от LamerOk

Попустись, дурачок.

Дурачок - это LamerOk, причём совершенно буквально.

Если твой голдштейн из США / Британии, то его правильный перевод имени будет именно «Ноа».

А почему не Ной? Почему ты резко перешёл на фонетическое транслитерирование? Потому что дурачок?

zg
() автор топика
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.