ПрограммированиеФорумОбщее

Как быстрее очистить большой кусок памяти? (C++) (2 стр)

Страницы: 1 2 3 49 Следующая »
#15
9:58, 15 янв 2011

1. Поиграй с длиной куска для заполнения. 16,32,64 бита за раз. Что-то даст профит по сравнению с остальным. НЕ по байту-это точно.
2. Поищи сторониие реализации типа того же memset от Intel

#16
13:49, 15 янв 2011

stream
> Зачем делать buf[k] = buf[k-1]? Какой тут профит, кроме лишнего чтения из
> памяти.

Команда movsd работает быстрее, чем stosd.
Лишние чтения во время интенсивной записи могут помочь, если кусок не в кеше. Они кешируют кусок. А запись этого не делает.

#17
14:22, 15 янв 2011

kas
  > какие твои доказательства? ты мерял, или так, языком почесать?
  Напиши superpuper_memzero(.....) , чтобы работало в тыщщу раз быстрее.


innuendo
> сравни memset и заполнение по mmx\sse
Сам сравни.. создай новый проект и ставни...

Делать нех больше как хнёй страдать.

#18
14:35, 15 янв 2011

memset по идее уже оптимизирован под максимально быструю работу. Его и использовать.

#19
14:40, 15 янв 2011

zlos
> memset по идее уже оптимизирован под максимально быструю работу. Его и
> использовать.
Причем интеловский мемсет (___intel_VEC_memzero) оптимизирован под разные процы одновременно. Вот например кусок из него:

.text:004019A8                 test    ___intel_cpu_indicator, 400h
.text:004019B2                 jnz     loc_401B00
.text:004019B8                 test    ___intel_cpu_indicator, 0FFFFFE00h
.text:004019C2                 jnz     loc_4019F0
.text:004019C8                 test    ___intel_cpu_indicator, 0FFFFFF80h
.text:004019D2                 jnz     loc_401B00
.text:004019D8                 test    ___intel_cpu_indicator, 0FFFFFFFFh
.text:004019E2                 jnz     loc_401B20
.text:004019E8                 call    ___intel_cpu_indicator_init


И один из этих переходов в зависимости от модели CPU содержит:

.text:00401A20                 movdqa  oword ptr [edi], xmm0
.text:00401A24                 movdqa  oword ptr [edi+10h], xmm0
.text:00401A29                 movdqa  oword ptr [edi+20h], xmm0
.text:00401A2E                 movdqa  oword ptr [edi+30h], xmm0
.text:00401A33                 movdqa  oword ptr [edi+40h], xmm0
.text:00401A38                 movdqa  oword ptr [edi+50h], xmm0
.text:00401A3D                 movdqa  oword ptr [edi+60h], xmm0
.text:00401A42                 movdqa  oword ptr [edi+70h], xmm0
.text:00401A47                 lea     edi, [edi+80h]
.text:00401A4D                 dec     ecx
.text:00401A4E                 jnz     short loc_401A20

Интел компилятор просто ухахатывается с потуг .L провелосипедить в нулевом посте и смотрит на остальных как сами знаете на что.

#20
15:07, 15 янв 2011

RtlFillMemory ^_^

#21
15:13, 15 янв 2011

Alexander K
> RtlFillMemory ^_^
И получи максимально тупой вариант:
http://pastebin.com/enea3Trh

#22
15:21, 15 янв 2011

entryway
По скорости тоже самое, что и memset, и ручное задание каждого байта (не на асме).

#23
15:27, 15 янв 2011

Простейше-тупейший memset который я всегда юзаю, работает быстрее орегинала в 4*num_cpu_cores раз =)

void _memset(void *data, int ch, size_t len)
{
     int *ptr = (int*)data;

     #pragma omp parallel for
     for(size_t i = 0; i < len; i++)
        ptr[i] = ch;
}
#24
15:32, 15 янв 2011

OpenDX
Твой мемсет (без прагмы омп) у меня выдаёт 0.017-0.018 мс, против 0.012 мс RtlFillMemory на одних и тех же данных.

#25
15:42, 15 янв 2011

Alexander K
> По скорости тоже самое, что и memset
Компиляторы бывают разные. Не у всех memset это аналог (или тоже самое, но по 4 байта):

while (count--) {
  *(char *)dst = (char)val;
  dst = (char *)dst + 1;
}

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

#26
15:43, 15 янв 2011

Alexander K

Ну вот, практически догнал Micro$, а по сравнению с их версией memset, мой код на выставку тока xD
Вот их memset

EXTERN_C void * __cdecl memset(void *d, int v, size_t c)
{
    if ((((ADDRESS) d) | c) & (sizeof(UINT) - 1)) {

        BYTE *pD = (BYTE *) d;
        BYTE *pE = (BYTE *) (((ADDRESS) d) + c);

        while (pD != pE)
            *(pD++) = (BYTE) v;

    }
    else {

        UINT *pD = (UINT *) d;
        UINT *pE = (UINT *) (BYTE *) (((ADDRESS) d) + c);
        UINT uv;

        uv = ((UINT) (v & 0xff)) | (((UINT) (v & 0xff)) << 8);

        /* Our processors are at least 32 bits
         */
        uv |= uv << 16;

#if (_UINTSIZE == 64)
        /* They might be 64 bits
         */
        uv |= uv << 32;
#endif

        while (pD != pE)
            *(pD++) = uv;
    }
    return d;
}

А вот еще какой-то мемсет из интернета на Си:

void *
memset(dst0, c0, length)
  void *dst0;
  register int c0;
  register size_t length;
#endif
{
  register size_t t;
  register u_int c;
  register u_char *dst;

  dst = dst0;
  /*
   * If not enough words, just fill bytes.  A length >= 2 words
   * guarantees that at least one of them is `complete' after
   * any necessary alignment.  For instance:
   *
   *  |-----------|-----------|-----------|
   *  |00|01|02|03|04|05|06|07|08|09|0A|00|
   *            ^---------------------^
   *     dst     dst+length-1
   *
   * but we use a minimum of 3 here since the overhead of the code
   * to do word writes is substantial.
   */ 
  if (length < 3 * wsize) {
    while (length != 0) {
      *dst++ = VAL;
      --length;
    }
    RETURN;
  }

#ifndef BZERO
  if ((c = (u_char)c0) != 0) {  /* Fill the word. */
    c = (c << 8) | c;  /* u_int is 16 bits. */
#if UINT_MAX > 0xffff
    c = (c << 16) | c;  /* u_int is 32 bits. */
#endif
#if UINT_MAX > 0xffffffff
    c = (c << 32) | c;  /* u_int is 64 bits. */
#endif
  }
#endif
  /* Align destination by filling in bytes. */
  if ((t = (int)dst & wmask) != 0) {
    t = wsize - t;
    length -= t;
    do {
      *dst++ = VAL;
    } while (--t != 0);
  }

  /* Fill words.  Length was >= 2*words so we know t >= 1 here. */
  t = length / wsize;
  do {
    *(u_int *)dst = WIDEVAL;
    dst += wsize;
  } while (--t != 0);

  /* Mop up trailing bytes, if any. */
  t = length & wmask;
  if (t != 0)
    do {
      *dst++ = VAL;
    } while (--t != 0);
  RETURN;
}
#27
15:46, 15 янв 2011

entryway
> while (count--) { *(char *)dst = (char)val; dst = (char *)dst + 1; }
0.012 мс.

P.S. компилятор MSVC++ или как он там называется, короче Visual Studio 2008.

#28
15:57, 15 янв 2011

OpenDX
> uv = ((UINT) (v & 0xff)) | (((UINT) (v & 0xff)) << 8);

Это в микрософте так пишут v & 0xffff?

OpenDX
> & (sizeof(UINT) - 1)
> #if (_UINTSIZE == 64)

Это 2 строчки писали 2 разных человека?

Alexander K
> RtlFillMemory

Это же rep stosd?

#29
16:01, 15 янв 2011

TarasB
> > RtlFillMemory
>
> Это же rep stosd?
Не знаю, не проверял. Вроде как это тот же самый memset.

Страницы: 1 2 3 49 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.