Есть ли memset (), который принимает целые числа, больше, чем символ?

31
задан Coren 9 February 2012 в 17:07
поделиться

6 ответов

void memset64( void * dest, uint64_t value, uintptr_t size )
{
  uintptr_t i;
  for( i = 0; i < (size & (~7)); i+=8 )
  {
    memcpy( ((char*)dest) + i, &value, 8 );
  }  
  for( ; i < size; i++ )
  {
    ((char*)dest)[i] = ((char*)&value)[i&7];
  }  
}

(Объяснение, согласно просьбе в комментариях: когда Вы присваиваете указателю, компилятор предполагает, что указатель выровненный к естественному выравниванию типа; для uint64_t, который составляет 8 байтов. memcpy () не делает такого предположения. На некоторых аппаратных средствах невыровненные доступы невозможны, таким образом, присвоение не является подходящим решением, если Вы не знаете невыровненную работу доступов над аппаратными средствами с маленьким или никаким штрафом, или знаете, что они никогда не будут происходить, или оба. Компилятор заменит маленький memcpy () s и memset () s с более подходящим кодом, таким образом, это не будет столь же ужасно, это взгляды; но если Вы действительно знаете достаточно, чтобы гарантировать, что присвоение будет всегда работать, и Ваш профилировщик говорит Вам, что это быстрее, можно заменить memcpy присвоением. Второе для () цикл присутствует в случае, если объем памяти, чтобы быть заполненным не является несколькими 64 битами. Если Вы знаете, что это всегда будет, можно просто отбросить тот цикл.)

31
ответ дан 27 November 2019 в 22:08
поделиться

Проверьте свою документацию ОС на локальную версию, затем рассмотрите просто использование цикла.

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

Оборачивают его как библиотеку и компилируют его со всей оптимизацией улучшения скорости, которую позволяет компилятор.

6
ответ дан 27 November 2019 в 22:08
поделиться

Нет никакой стандартной библиотечной функции afaik. Таким образом, при написании портативного кода Вы смотрите на цикл.

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

способ, которым Вы записали бы свое собственное, зависит от того, можно ли определить в API, что вызывающая сторона гарантирует, что dst указатель будет достаточно выровненный для 64-разрядных записей на платформе (или платформах если портативен). На любой платформе, которая имеет 64-разрядный целый тип вообще, malloc, по крайней мере, возвратит соответственно выровненные указатели.

, Если необходимо справиться с неприсоединением, затем Вам нужно что-то как ответ moonshadow. Компилятор может встроить/развернуть это memcpy с размером 8 (и использовать 32-или 64-разрядная невыровненная операция в секунду записи, если они будут существовать), таким образом, код должен быть довольно холодным, но мое предположение - это, то вероятно, не будет особый случай целая функция для места назначения, бывшего выровненный. Я хотел бы быть исправленным, но бояться, что я не буду.

Поэтому, если Вы знаете, что вызывающая сторона будет всегда давать Вам dst с достаточным выравниванием для Вашей архитектуры и длину, которая является кратной 8 байтам, затем делайте записи простого цикла uint64_t (или независимо от того, что 64-разрядный интервал находится в Вашем компиляторе), и Вы будете, вероятно (никакие обещания) заканчиваются с более быстрым кодом. У Вас, конечно, будет более короткий код.

Независимо от того, что случай, если Вы действительно заботитесь о производительности затем, представляет ее. Если это не достаточно быстро, попробовали еще раз с большим количеством оптимизации. Если это все еще не достаточно быстро, задайте вопрос о asm версии для ЦП, на котором это не достаточно быстро. memcpy/memset может получить крупные увеличения производительности с оптимизации на платформу.

10
ответ дан 27 November 2019 в 22:08
поделиться

wmemset(3) широкая (16-разрядная) версия memset. Я думаю, что это является самым близким, Вы собираетесь войти в C без цикла.

4
ответ дан 27 November 2019 в 22:08
поделиться

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

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

//pseudo code
asm
{
    rep stosq ...
}

можно, вероятно, погуглить stosq команду блока для специфических особенностей. Это не должны быть больше, чем несколько строк кода.

1
ответ дан 27 November 2019 в 22:08
поделиться

запишите свое собственное; это тривиально даже в asm.

0
ответ дан 27 November 2019 в 22:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: