LINUX.ORG.RU
ФорумTalks

[ничего не поделаешь, это...] доставляющая история про memcpy


0

2

http://avva.livejournal.com/2323823.html

Для Ъ будут спойлеры:

29 сентября 2010 года. Пользователь "JCHuynh" открывает новый баг на сайте Федоры о том, что 64-битный флэш-плагин от Adobe перестал нормально проигрывать mp3-файлы, выдает все время какой-то треск вместо правильного звука.
В Интеле работают хорошие программисты
А в новой, при копировании от конца к началу, выходит ошибка. Но не всегда, а лишь на некоторых процессорах и в некоторых условиях. И пока что никто этого еще не знает, в конце июня прошлого лета. 

Чипсы это яд. Не жри чипсы, не жри!

★★★★☆

Ответ на: комментарий от geekless

>Потому что имплементация memcpy остаётся прежней.

Какой же ты тугой. Сначала определись, за что борешься. Не девочка и не ребенок, поди. Сначала ратуешь за вариант Линуса, тратишь на разжевывание тебе его несостоятельности мое время. Теперь цепляешься за изначальный вариант. Ну хорошо, я терпеливый.

Ещё раз сначала.

1)Ты понял, почему вариант Линуса не подходит? Если не понял, вдумчиво перечитай тред.

2)Ты понял, что патч от интела дает существенный прирост производительности? Если нет, сходи по ссылкам на багзилу. Там на английском языке, но хотя бы попробуй понять, напряги мозги.

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

Я прошу, чтобы вызов функции memcpy

там тысячи функций, к ним тоже претензии? :)

Веских причин, обосновывающих текущее поведение memcpy пока не привёл

O_O можно посмотреть на программы которые ты написал? Я уверен я найду кучу функций которые не проверяют аргументы. Потому что всё везде проверять можно только в отладочной версии.

серьёзно осложняет жизнь всем

ааа, убил. Запускаешь valgrind и он сразу показывает где проблема. Собстно так и нашли эту проблему. Это, кстати, показывает что разрабы адоба своих продуктов вообще не заморачиваются.

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

geekless в конец упорот :). Скажи ему что он своими действиями он пытается остановить эволюцию и что только спеки и спасают от вселенского хаоса. Нарушать спеки это всё равно что нарушать правила дорожного движения. По встречке зачастую можно ехать быстрее... (намёк на Томми)

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

Если подходить с такой меркой, то единственным приемлимым для всех решением является откатиться на классическую реализацию memcpy, после чего закрепить данное поведение в стандарте. Пусть эта функция лежит там древним говном мамонта для миллионов строк уже написанного кода, который её использует. Новому коду рекомендовать использовать memmove, и только её. В новой же версии спецификации C, если она когда-нибудь в будущем появится, и вовсе объявить её deprecated.

Вот это решение устроит всех. Кроме отдельной кучки фанатиков, у которых несоответствие действительности их фантазиям о ней вызывает лютый баттхерт.

Что тебе еще не ясно?

патч от интела дает существенный прирост производительности

Оптимизировать надо memmove. А в memcpy запилить тот код, который там был прежде.

Блджад, я тут уже 3 страницы об этом пишу, а до тебя всё никак не может дойти? Или ты просто читать не умеешь? Какой же ты тугой! (c)

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

>geekless в конец упорот :)

Согласен. Но все-таки, считаю, что он не безнадежен, поэтому и пытаюсь ему помочь.

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

>Оптимизировать надо memmove. А в memcpy запилить тот код, который там был прежде.

memmove можно оптимизировать только для частного случая. Или ты можешь подсказать мужикам общее решение?

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

оно должно делать это везде, на любом железе

Не должно. Оно вообще ничего не должно, оно имеет право разрушить Вселенную. BEHAVIOR IS UNDEFINED.

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

memmove можно оптимизировать только для частного случая. Или ты можешь подсказать мужикам общее решение?

Ты сам понял, что сказал? memcpy и есть частный случай memmove.

if (области не перекрываются) {
  копировать оптимизированным алгоритмом интела
} else {
  копировать алгоритмом для перекрывающихся областей
}

В этом псевдокоде что-нибудь не ясно?

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

>Ты сам понял, что сказал

У меня в голове полная картина. Чего нельзя сказать про тебя.

memcpy и есть частный случай memmove

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

P.S. Я некоторое время буду оффлай. Если тебе все ещё что-то непонятно, пиши, вечером продолжим наш урок.

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

> Проблема в том, что у memcpy есть дополнительные возможности, которыми некоторые программы пользуются. Поэтому заменить одну функцию на другую нельзя.

Ну давай, птица гордая, вещай.

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

Вокруг вполне достаточно грабель, незачем коварно прятать ещё одни.

Пока что я вижу что 1) коммит в глибц доломал худо-бедно работавшие программы, 2) memcpy относительно замедлилось и стало работать не быстрее memmove, 3) ни единого обоснования, почему коммит (1) вообще нужен.

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

Ну и еще. Чтобы ты опять не ходил кругами, вопрос повторю:

if (области не перекрываются) {
  копировать оптимизированным алгоритмом интела
} else {
  копировать алгоритмом для перекрывающихся областей
}

В этой реализации memmove что-нибудь не ясно?

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

Это не грабли. То есть это грабли, но они стоят на своём месте, и написано - «здесь грабли». В сарай можно зайти через дверь, а можно через чердак и дырку в полу чердака. Внизу, под дыркой, будут грабли. Или лопата. Или капкан медвежий. ХОДИ ЧЕРЕЗ ДВЕРЬ!

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

на одном железе делала одно, а на другом - другое

Вы упороты штоле? Результат работы memcpy одинаковый везде и всюду. А именно были байтики здесь, а теперь там. Но если области пересекаются - програмист из AdobeССЗБ.

nanoo_linux
()
Ответ на: комментарий от geekless

> В ту ветку управление вообще не попадает

я не понимаю. у тебя есть функция. это замена чего? memmove? глибцовая она работает и без того, твоя же реализация ее заменяет плохо. memcpy? она ее вообще не может заменить, ибо не работает для пересекающихся участков.

я почему-то решил, что ты хочешь показать как надо написать memcpy с сохранением скорости работы и без порчи памяти. я ошибся?

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

программист из Адоба тут вовсе ни при чём. Упоролись девелоперы глибц. Была нормальная, работающая версия их либы. Потом они приняли коммит, который доломал кривой софт, усложнил и затормозил memcpy до скорости memmove, добавил проблем с поиском багов всем прочим разработчикам.

Им говорят - регрессия, поправьте. Стандарт, конечно, не регламентирует поведение memcpy на пересекающихся областях, но это не повод пихать в область пересечения фигню. Можно в таких случаях тихо вызывать memmove. Это в той же мере будет соответствовать (или не соответствовать) стандарту.

Разработчики глибц почему-то упираются и обзывают всех прочих разработчиков криворукими. Да, разработчики флеш-плугина, сквашфс и гстримера накосячили. Но они всего лишь люди, и будут продолжать косячить. В чём проблема этот косяк пофиксить раз и навсегда?

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

> В чём проблема этот косяк пофиксить раз и навсегда?

Они это и сделали, раз и навсегда.

alpha ★★★★★
()

предлагаю всё же разговор вести в плоскости «зачем нужны спеки» и «что делать с плохими/устаревшими спеками и стандартами». Вопросы оптимизации тут вторичны.

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

добавил проблем с поиском багов всем прочим разработчикам.

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

будет соответствовать (или не соответствовать) стандарту

Зачем стандарты если ими не пользуются?

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

> Тех кого эти изменения затронули полные идиоты не умеющие пользоваться valgrind, таких не жалко.

Внезапно, на усложнение и замедление функции memcpy уже пофиг? Регрессия, притом явная. О причинах, по которым разработчики вдруг решили на это пойти никому не известно.

Зачем стандарты если ими не пользуются?

Ещё раз, в стандарте undefined. Не распространяется стандарт на этот случай.

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

Внезапно, на усложнение и замедление функции memcpy уже пофиг?

Ульрих пишет что он таки ускорился.

Ещё раз, в стандарте undefined. Не распространяется стандарт на этот случай.

Окей, почему бы в таком случае не использовать memmove на который «стандарт распространяется»? Ты возьмёшь на работу программиста который использует недокументированные фичи?

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

> Ульрих пишет что он таки ускорился.

Это зависит от того, с чем сравнивать. В старой реализации memcpy примерно на 20% быстрее memmove, в новой были ускорены обе функции. Линус проводил тесты, разницы в скорости новых memcpy и memmove ему обнаружить не удалось. Так что сами по себе функции ускорились, но отосительно memmove memcpy замедлился.

Окей, почему бы в таком случае не использовать memmove на который «стандарт распространяется»? Ты возьмёшь на работу программиста который использует недокументированные фичи?

Можно и нужно, конечно же. Иначе при портировании вылезут баги. Сейчас речь всего лишь о том, что разработчики глибц почему-то забили на идею «быстрый и тупой memcpy», но почему-то отказываются избавиться от лишней сущности.

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

если функция относительно старой себя ускорилась, то какая разница, что там с относительной скоростью к посторонней функции?

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

memcpy пришло к нам из тех времён, когда экономили каждый такт. Поэтому memcpy была весьма тупым (и по этой же причине быстрым) кодом. memmove является более умной (и медленной) альтернативой «на крайний случай», когда объекты пересекаются, а скопировать таки надо.

Сейчас всякая нужда экономить такты на разнице между memcpy и memmove отпала, что с успехом продемонстрировали разработчики glibc. Однако, раз уж эти функции теперь являются полным дубликатом, то неясно зачем их держать обе? Вполне можно оставить одну.

Более того, с ходу можно предложить другой, ещё более хороший вариант (он тут проскакивал):

if (области не перекрываются) {
  копировать тупым быстрым алгоритмом
} else {
  копировать алгоритмом для перекрывающихся областей
}

Это будет быстрее, чем текущий вариант (за счёт тупого быстрого алгоритма, который будет работать в большинстве случаев), надёжнее (будет вести себя одинаково везде и не будет портить данные в памяти ни при каких условиях), оптимизировать всё можно в одном месте, вместо двух итд.

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

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

откуда ты взял утверждение про «полный дубликат»? и тут же далее написал, что они делают разные вещи

разные функции, по-разному описаны в стандарте, с разной физической реализацией

код оптимизирован, у пользователей библиотеки есть книжка со спецификацией

if (области не перекрываются)


эта проверка происходит забесплатно?

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

Тут все орут, что memmove будет работать медленнее memcpy при копировании непересекающихся участков из-за невозможности чего-то там оптимизировать. Мой код — демонстрация пути в коде, который отрабатывает, когда memmove используется для копирования непересекающихся участков. Вызов memmove -> проверка непересечения -> выполнение алгоритма, эквивалентного memcpy. (Предполагается, что будет использован оптимизированный алгоритм интела. Для теста нам, впрочем, это не важно.) Мой код наглядно показывает, что проход этого пути в коде не оказывает никакого существенного влияния на скорость, по сравнению с прямым вызовом копирующего алгоритма.

Пока кто-нибудь другой наглядно не продемонстрировал обратное, все аргументы о невозможности везде в программах использовать memmove вместо memcpy по причинам производительности — несостоятельны.

Еще раз, что я полагаю верным решением ситуации с memcpy:

1. Законсервировать реализацию memcpy.
2. Оптимизировать memmove.
3. Предложить (в документации) всему новому коду использовать memmove как более оптимизированный и безопасный аналог memcpy. Для большей весомости предложения можно сыпать ворнингами при использовании memcpy.
4. Предложить объявить в стандарте memcpy deprecated.

Что тут может быть не ясно?

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

> Мой код — демонстрация пути в коде, который отрабатывает, когда memmove используется для копирования непересекающихся участков. Вызов memmove -> проверка непересечения -> выполнение алгоритма, эквивалентного memcpy.

отличный план. memmove, внезапно, так и работает. только проблема в том, что адоб memmove почему-то не использует, хотя надо бы.

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

будет вести себя одинаково везде и не будет портить данные в памяти ни при каких условиях

При правильном использовании memcpy не портит данные. А на счёт «будет вести себя одинаково везде», осмелюсь предположить, что у вас не правильное представление о том, что такое интерфейс. Эта ф-ия ведёт себя везде и всюду одинаково, пока области не пересекаются. ЕСЛИ ОНИ ПЕРЕСЕКАЮТСЯ - MEMCPY ИСПОЛЬЗОВАТЬ НЕЛЬЗЯ. Извините за капс, но как вам ещё объяснить? А разработчики в Adobe тем и отличились, что использовали эту ф-ию когда области пересекаются. Имхо, канонический быдлопрограмизм.

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

Спасибо, я в курсе что некоторые (разработчики глибц в частности) считают undefined behavior поводом, чтобы портить данные. Только сегодня и только для них я предлагаю альтернативную реализацию memcpy, которая ещё лучше справляется с задачей.

Выкидываем оттуда все мудрствования вроде определения направления копирования на некоторых типах процессоров, вместо этого вставляем проверку на пересечение и, если оно найдено то забиваем src и dst случайными числами.

Быстро, эффективно, 100% гарантия порчи данных. Полагаю, что это и есть тот самый идеал, который некоторые люди стремятся достичь.

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

Сейчас речь всего лишь о том, что разработчики глибц почему-то забили на идею «быстрый и тупой memcpy», но почему-то отказываются избавиться от лишней сущности.

Ты определись в чём проблема. Сначала писал что разрабы glibc должны плясать под дудку адоба, теперь же речь идёт о внутренних оптимизациях.

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

Я определился с самого начала. Говорил я всегда лишь о выявившихся внутренних проблемах самого глибц. К несчастью, локализовать проблему удалось с помощью криво написанного флеш-плагина, и теперь огромное количество людей считает, что баг в багзилле глибц означает «почините нам наш флеш».

Так вот, ничего подобного. Начиная с первого своего сообщения в этой ветке я писал:

Их новая функция memcpy делает разные вещи на разном железе. Это баг и этот код должен быть выпилен в пользу кода, который одинаково работает на любом железе.

Проблема в том, что открытый баг разработчики глибц видят как «криво написанный флеш-плагин не работает на вашем глибц, пофиксите» и активно возражают. Да, флеш-плагин написан криво. Но пофиксить глибц нужно не затем, чтобы он заработал. Например, фикс когда memcpy всегда и везде копирует задом-наперёд будет фиксом для глибц, но флеш останется поломанным.

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

функция memcpy делает разные вещи на разном железе

Железо разное. Разное железо требует разных оптимизаций. Если писать одинаково для всех платформ то производительность на некоторых платформах будет низкой. Ты с этим согласен?

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

Да, с этим я согласен. Но к данному вопросу это не имеет ни малейшего отношения, скорость работы memcpy и memmove оказалась одинаковой. Иными словами был положен болт как на оптимизацию, так и на исторические причины.

Итого - причины, по которым грабли были положены исчезли, сами грабли остались. Может их пора убрать?

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

Можно ссылочку на бенчмарк? Я не нашёл ни одного, кроме как на сайте интеля что при использовании sse2 ускорение идёт на 20%.

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

Можно, конечно. Вот: https://bugzilla.redhat.com/show_bug.cgi?id=638477#c46

I did both cached (same block over and over) and non-cached (a million blocks in sequence).

For the cached case my stupid LD_PRELOAD version was consistently a bit faster.

The noise on the non-cached case was larger, but the glibc memcpy may have been faster. I say «may have been» because it went both ways: I did ten runs, and my LD_PRELOAD one still won 6 out of those 10 runs, but the noise was large enough that I will allow that I'm not going to guarantee anything.

Do I have a point? I bothered to _measure_ the speed, and according to my measurements, glibc wasn't any faster than my trivial version and was likely slower. But I only tested two cases.

Alan_Steel ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.