Что самый эффективный путь состоит в том, чтобы сравнить два блока памяти на языке D?

Для записей == 0, решение rjmunro дает 1. Правильное решение 0. Тем не менее, если Вы знаете, что записи> 0 (и я уверен, что мы все приняли, recordsPerPage> 0), затем rjmunro решение дает корректные результаты и не имеет ни одной из водосливных проблем.

int pageCount = 0;
if (records > 0)
{
    pageCount = (((records - 1) / recordsPerPage) + 1);
}
// no else required

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

7
задан Ciro Santilli 新疆改造中心法轮功六四事件 24 April 2015 в 20:43
поделиться

5 ответов

Вы можете попробовать:

  • проверить, является ли uint наибольшим типом, подходящим для вашего целевого ЦП (ulongs могут лучше соответствовать собственному регистру)
  • используйте 2 указателя этого типа
  • использовать 2 локальные переменные, используя * p ++ (не разыменовывайте указатели 2 раза для 1 значения)
  • делите счетчик 1-го цикла вперед (используйте while (counter -))
  • разверните 2-й цикл, заменив его с помощью переключателя (если sizeof (тип, который помещается в регистр) известен и всегда будет одним и тем же.)

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

uint* lp = (uint*)lhs;
uint* rp = (uint*)rhs;
uint  l;
uint  r;
int count = (n / uint.sizeof) / 4;

while (count--) {
    if( (l = *lp++) != (r = *rp++) {
        return (l < r) ? -1 : 1;
    }
    if( (l = *lp++) != (r = *rp++) {
        return (l < r) ? -1 : 1;
    }
    if( (l = *lp++) != (r = *rp++) {
        return (l < r) ? -1 : 1;
    }
    if( (l = *lp++) != (r = *rp++) {
        return (l < r) ? -1 : 1;
    }
}

Конечно, остается (n / uint.sizeof)% 4 итераций, которые нужно сделать, что вы можете смешать этот цикл, чередуя переключатель,

3
ответ дан 7 December 2019 в 03:17
поделиться

Я мало что знаю об этом, но есть векторные инструкции, которые могут применять инструкции ко многим байтам одновременно. Вы можете использовать эти результаты для невероятно быстрой работы с memcmp. Я не знаю, какие инструкции вам понадобятся, но если вы посмотрите Новые инструкции Larrabee или прочтете эту статью, вы можете найти то, что ищете http://www.ddj.com/architect/216402188

ПРИМЕЧАНИЕ: Этот процессор отсутствует в ATM AFAIK

-Edit- Сейчас я уверен, что есть наборы инструкций (попробуйте SSE или SSE2), которые могут сравнивать сразу 16 байтов, если они выровнены.

Вы можете попробовать это в чистом виде. код c ++.

template<class T>
int memoryCompare(const T* lhs, const T * rhs, size_t n) {
    const T* endLHS = lhs + n/sizeof(T);
    while(lhs<endLHS) {
        int i = *lhs - *rhs;
        if(i != 0) return i > 0 ? 1 : -1;
        lhs++;
        rhs++;
    }
    //more code for the remaining bytes or call memoryCompare<char>(lhs, rhs, n%sizeof(T));
    return 0;
}

Преимущество здесь заключается в том, что вы увеличиваете указатель, чтобы вы могли разыменовать его и не применять индекс (его ptr_offset [index] vs ptr_offset). В приведенном выше примере используется шаблон, поэтому вы можете использовать 64-разрядные версии на 64-разрядных машинах. и CMP в сборке на самом деле просто вычитание проверки флагов N и Z. Вместо того, чтобы сравнивать N и уменьшать N i, просто сравните в моей версии.

2
ответ дан 7 December 2019 в 03:17
поделиться

Помогает ли вам ответ на этот вопрос ?

Если компилятор поддерживает реализацию memcmp () в качестве встроенной / встроенной функции, похоже, вам будет сложно ее превзойти.

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

1
ответ дан 7 December 2019 в 03:17
поделиться

Я думаю, что memcmp предназначен для побайтового сравнения, независимо от типа данных. Вы уверены, что реализация вашего компилятора сохраняет семантику строк? Не должно.

1
ответ дан 7 December 2019 в 03:17
поделиться

Well a lot depends upon your system and data. There is only so many assumptions we can make. What processor are you using? Does it have to be straight C code? How wide are the CPU registers? What is the cache structure of the CPU? etc etc

It also depends on how different your data is. If it is very unlikely that the first byte from each buffer is the same then the speed of the function is pretty meaningless as, logically, it won't get to the rest of the function. If it is likely that the first n-1 bytes are usually the sme then it becomes more important.

All in you are unlikely to see much change regardless of how you do the test.

Anyway this is a little implementation of my own, it may, or may not, be faster than your own (or, given i just made it up as i went along, it may, or may not, work ;)):

int memoryCompare(const void* lhs, const void* rhs, size_t n) 
{
    uint_64 diff    = 0

    // Test the first few bytes until we are 32-bit aligned.
    while( (n & 0x3) != 0 && diff != 0 )
    {
        diff = (uint_8*)lhs - (uint_8*)rhs;
        n--;
        ((uint_8*)lhs)++;
        ((uint_8*)rhs)++;              
        }

    // Test the next set of 32-bit integers using comparisons with
    // aligned data.
    while( n > sizeof( uint_32 ) && diff != 0 )
    {
        diff = (uint_32*)lhs - (uint_32*)rhs;
        n   -= sizeof( uint_32 );
        ((uint_32*)lhs)++;
        ((uint_32*)rhs)++;
    }

    // now do final bytes.
    while( n > 0 && diff != 0 ) 
        {
        diff = (uint_8*)lhs - (uint_8*)rhs;
        n--;
        ((uint_8*)lhs)++;
        ((uint_8*)rhs)++;  
        }

    return (int)*diff / abs( diff ));
}
1
ответ дан 7 December 2019 в 03:17
поделиться
Другие вопросы по тегам:

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