Добрый день, коллеги.
Подскажите самый быстрый способ обнулить блок памяти (1000000 байт)?
PS Кроме SSE инструкций (заполнять по 16 байт) ничего нет?
Re: Быстрый способ обнулить блок памяти?
От:
Аноним
Дата:
10.09.11 09:11
Оценка:
Здравствуйте, nbie, Вы писали:
N>Добрый день, коллеги. N>Подскажите самый быстрый способ обнулить блок памяти (1000000 байт)?
N>PS Кроме SSE инструкций (заполнять по 16 байт) ничего нет?
А что за ОС?
В Линукс можно выполнить mmap() нужного размера куска файла /dev/zero в память.
А>А что за ОС? А>В Линукс можно выполнить mmap() нужного размера куска файла /dev/zero в память.
Пардон, Windows.
PS Но если говорить про linux: за счет чего такая операция имеет выигрыш производительности? Разве работа функции не сводится к побайтовому копированию или блочному по 16?
N>PS Но если говорить про linux: за счет чего такая операция имеет выигрыш производительности? Разве работа функции не сводится к побайтовому копированию или блочному по 16?
за счет откладывания уплаты стоимости на момент(ы) первого доступа к этой памяти
N>>PS Но если говорить про linux: за счет чего такая операция имеет выигрыш производительности? Разве работа функции не сводится к побайтовому копированию или блочному по 16? D>за счет откладывания уплаты стоимости на момент(ы) первого доступа к этой памяти
Очень интересно. Подобного в Windows нет?
Могли бы сказать ключевые слова для поиска инф, чтобы понять смысл этих слов? ) Или разъяснить.
D>>за счет откладывания уплаты стоимости на момент(ы) первого доступа к этой памяти
N>Очень интересно. Подобного в Windows нет? N>Могли бы сказать ключевые слова для поиска инф, чтобы понять смысл этих слов? ) Или разъяснить.
примерно по тем же принципам по которым работает своп.
Современные процессоры автоматически отображают виртуальные адреса в физические. Если код пытается обратиться по виртуальному адресу который ни на что не отображается, то происходит trap и управление передается ОС. ОС смотрит что такое, и может разрешить это обращение, настроив отображение для этого адреса (для этой страницы памяти)
Когда ты делаешь mmap на /dev/zero то тебе просто выдают указатель на неициализированную память (которая не отображена ни на какие реальные адреса). Когда ты пытаешься обратится к ней, то срабатывает ловушка и ОС выделяет страницу памяти заполненную нулями.
Здравствуйте, dilmah, Вы писали:
D>Когда ты делаешь mmap на /dev/zero то тебе просто выдают указатель на неициализированную память (которая не отображена ни на какие реальные адреса). Когда ты пытаешься обратится к ней, то срабатывает ловушка и ОС выделяет страницу памяти заполненную нулями.
Угу. Иными словами, к цене memset() добавляется цена обработки (аппаратного) исключения.
Здравствуйте, nbie, Вы писали:
N>Подскажите самый быстрый способ обнулить блок памяти (1000000 байт)?
Я бы начал с memset(), собрав программу под соответствующий процессор (а не под generic i386), и разрешив компилятору инлайнить такие функции. memset() не так уж наивно устроен. Потом я бы померил получившуюся скорость, сравнил бы ее с теоретическим пределом, и либо успокоился, либо сел бы думать дальше.
Здравствуйте, Pzz, Вы писали:
Pzz>Здравствуйте, nbie, Вы писали:
N>>Подскажите самый быстрый способ обнулить блок памяти (1000000 байт)?
Pzz>Я бы начал с memset(), собрав программу под соответствующий процессор (а не под generic i386), и разрешив компилятору инлайнить такие функции. memset() не так уж наивно устроен. Потом я бы померил получившуюся скорость, сравнил бы ее с теоретическим пределом, и либо успокоился, либо сел бы думать дальше.
memset внутри себя вызывает SSE2 в определенных случаях. Случай ТС как раз такой. Поэтому имеет смысл попробовать SSE2 напрямую — обойтись без лишних проверок (а у ТС размер массива кратен 4). Будет ли эффект — трудно сказать.
Насчет инлайнить — можн поподробнее ? Трассировка в режиме релиз показывает, что она вызывается из библиотеки.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>memset внутри себя вызывает SSE2 в определенных случаях. Случай ТС как раз такой. Поэтому имеет смысл попробовать SSE2 напрямую — обойтись без лишних проверок (а у ТС размер массива кратен 4). Будет ли эффект — трудно сказать.
При таком размере накладные расходы от этих проверок — копейки. Я бы не стал тратить время на возню с SSE, если memset достаточно хорош.
PD>Насчет инлайнить — можн поподробнее ? Трассировка в режиме релиз показывает, что она вызывается из библиотеки.
N>>>Подскажите самый быстрый способ обнулить блок памяти (1000000 байт)?
Pzz>>Я бы начал с memset(), собрав программу под соответствующий процессор (а не под generic i386), и разрешив компилятору инлайнить такие функции. memset() не так уж наивно устроен. Потом я бы померил получившуюся скорость, сравнил бы ее с теоретическим пределом, и либо успокоился, либо сел бы думать дальше.
PD>memset внутри себя вызывает SSE2 в определенных случаях. Случай ТС как раз такой. Поэтому имеет смысл попробовать SSE2 напрямую — обойтись без лишних проверок (а у ТС размер массива кратен 4). Будет ли эффект — трудно сказать.
Присоединяюсь к вопросу. Если заполнение блоками по 16 байт — это максимум скорости, то проделать это самому в цикле разве не будет оптимальным?
PS Кстати, может кто сказать почему в SSE 16 максимум (?)? Почему не больше?
И, пардон, что такое "TC"?
Здравствуйте, nbie, Вы писали:
N>Присоединяюсь к вопросу. Если заполнение блоками по 16 байт — это максимум скорости, то проделать это самому в цикле разве не будет оптимальным?
Тот же memset, только без проверок на случай, если размер не кратен 16.
N>PS Кстати, может кто сказать почему в SSE 16 максимум (?)? Почему не больше?
16 * 8 = 128 — разрядность SSE
N>И, пардон, что такое "TC"?
Здравствуйте, nbie, Вы писали:
PD>>memset внутри себя вызывает SSE2 в определенных случаях. Случай ТС как раз такой. Поэтому имеет смысл попробовать SSE2 напрямую — обойтись без лишних проверок (а у ТС размер массива кратен 4). Будет ли эффект — трудно сказать.
N>Присоединяюсь к вопросу. Если заполнение блоками по 16 байт — это максимум скорости, то проделать это самому в цикле разве не будет оптимальным?
Это вы кеш заполняете блоками по 16 байт. А из кеша в память льется струей.
N>PS Кстати, может кто сказать почему в SSE 16 максимум (?)? Почему не больше?
Потому что самые большие програмно доступные регистры у x86 — это 16-байтные регистры SSE
N>И, пардон, что такое "TC"?
Здравствуйте, Pzz, Вы писали:
Pzz>Это от компилятора зависит. gcc инлайнит эти функции, если оптимизация включена. Насчет MSVC я не особенно копенгаген . Смотрите здесь: http://msdn.microsoft.com/en-us/library/26td21ds.aspx
Черт его знает. /Oi установил, Release, но все равно call и jmp в адреса 0x7xxxxxxx. Может, что-то не так делаю. А впрочем, ты прав — на миллион байт это все копейки.
Коллеги, все понял, кроме этого:
N> Если заполнение блоками по 16 байт — это максимум скорости, то проделать это самому в цикле разве не будет оптимальным? P> Это вы кеш заполняете блоками по 16 байт. А из кеша в память льется струей.
Поясните еще раз эту мысль ("А из кеша в память льется струей" — к чему это).
Я, конечно пойду читать про кеш, но я думал я заполняю память по указателю непосредственно.
Здравствуйте, nbie, Вы писали:
N>Поясните еще раз эту мысль ("А из кеша в память льется струей" — к чему это). N>Я, конечно пойду читать про кеш, но я думал я заполняю память по указателю непосредственно.
Вы пишете в кеш. Это такая маленькая быстрая память, припаянная прямо к процессору. Процессор потом, по своему усмотрению и без вашего участия, перемещает данные из кеша в память — да еще и с промежуточным буферированием в контроллере памяти.
Из кеша в контроллер памяти данные уходят блоками размером с cache line (это минимальная единица обмена между кешом и системной памятью). У современных x86-х процессоров кеш-лайн имеет размер 64 байта. Контроллер же памяти старается склеить эти обращения так, чтобы набрать целую "строку": работа "строками" — это самый быстрый способ работы с памятью. Чему сейчас равна строка, я даже и не знаю.
Здравствуйте, nbie, Вы писали:
N>Добрый день, коллеги. N>Подскажите самый быстрый способ обнулить блок памяти (1000000 байт)?
самый бйстрый способ его просто выкинуть и выделить новый через virtualalloc
там он гарантированно будет забит нулями и занимается этим system idle process
N>Добрый день, коллеги. N>Подскажите самый быстрый способ обнулить блок памяти (1000000 байт)?
N>PS Кроме SSE инструкций (заполнять по 16 байт) ничего нет?
вот тут есть какие-то слова по этому поводу http://lwn.net/Articles/255364/
общая идея в том, что кеш использовать в этом случае не надо — это дополнительные затраты на чтение кешлайна, модификацию и запись назад.
кстат про sse, если у gcc задать уровень оптимизации -O3, то он даже для
for(i = 0; i<много; i++)
buffer[i] = 0;
будет использовать sse инструкции, и я думаю в этих вопросах можно положиться на libc и gcc, ну или их виндовые аналоги.
Здравствуйте, nbie, Вы писали:
N>Добрый день, коллеги. N>Подскажите самый быстрый способ обнулить блок памяти (1000000 байт)?
N>PS Кроме SSE инструкций (заполнять по 16 байт) ничего нет?
В микроволновку на 2-3 секунды. Обнулится по первому классу.