2016-02-05 3 views
4

Я хочу написать код memcpy, который вместо слова by by by by by by copy, чтобы увеличить скорость. (Хотя мне нужно сделать несколько байтов по байтам для последних или нескольких байтов). Поэтому я хочу, чтобы мой исходный адрес и адрес назначения были правильно выровнены. Я видел реализацию memcpy в glibc https://fossies.org/dox/glibc-2.22/string_2memcpy_8c_source.html он выполняет выравнивание только для адреса назначения. Но даже если адрес источника не правильно выровнен, это приведет к ошибке шины (проверьте, что проверка выравнивания включена в моем процессоре). Я не уверен, как правильно настроить выравнивание источника и адресата. Потому что, если я попытаюсь выровнять исходный код, скопировав несколько байтов по байтам, он также изменит адрес назначения, поэтому сначала адрес назначения, который был правильно выровнен, может быть неправильно выровнен. Так есть способ выравнивания обоих ?. Пожалуйста, помогите мне.Выравнивание как исходного, так и целевого адреса в memcpy

void memcpy(void *dst, void *src,int size) 
{ 
    if(size >= 8) 
    { 
    while(size/8) /* code will give sigbus error if src = 0x10003 and dst = 0x100000 */ 
    { 
     *((double*)dst)++ = *((double*)src)++; 
     size = size - 8; 
    } 
    } 

    while(size--) 
    { 
    *((char*)dst)++ = *((char*)src)++; 
    } 
} 
+1

Я не понимаю, как вы могли бы выровнять исходный адрес и dest? Извините, я просто не понимаю? –

+0

@MartinJames Рассмотрим, что я передаю src = 0x10003 dest = 0x100000 и размер 15. Если в memcpy я хочу сделать слово за словом copy, я хочу, чтобы src был кратным 8 (64-разрядная ОС), поэтому следующий номер, который кратно 8 - 0x10006, поэтому для первых 3 байтов я сделаю байтовую копию по байтам, если я сделаю это, то src будет 0x10006, но dest = 0x100003, опять же dest не будет кратным 8. эта проблема будет продолжена. Итак, как я могу выровнять оба src и dest здесь. Если его невозможно, есть ли другой способ сделать слово за словом? – Praveen

+0

Вы не можете. Предполагая, что вы перемещаете блок слов, если источник нечетный, но цель четная, вы в некотором смысле выравниваете несогласованные слова. С другой стороны, если источник четный, а цель нечетна, вы смещаете выровненные слова.Вы будете либо читать, либо писать несогласованные слова - это не совсем так, как копировать байт за раз. –

ответ

0

... так что в первый адрес назначения, который был приведен в соответствие на первый правильно может не быть выровнены должным образом в настоящее время. Так есть ли способ выровнять оба?

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

модифицированного алгоритма GNU:

void * memcpy(void * dst, void const * src, size_t len) 
{ 
    long * plDst = (long *) dst; 
    long const * plSrc = (long const *) src; 

    if (!(src & 0xFFFFFFFC) && !(dst & 0xFFFFFFFC)) 
    { 
     while (len >= 4) 
    { 
      *plDst++ = *plSrc++; 
      len -= 4; 
     } 
    } 

    char * pcDst = (char *) plDst; 
    char const * pcDst = (char const *) plSrc; 

    while (len--) 
    { 
     *pcDst++ = *pcSrc++; 
    } 

    return (dst); 
} 

Thisизменение алгоритма измененного-GNU использует вычисление для корректировки смещения адреса.

+1

Благодарим вас за ответ, но здесь код сначала проверяет, совпадают ли оба адресата и источник 4 байт. если они выровнены, он делает длинную копию. else byte by byte copy. Но если размер более 1000, для скорости, до некоторого момента я буду делать байты с байтом, пока оба моих src и dest не будут выровнены. затем плохо делайте слово за словом, а оставшиеся больные снова делаете байт заново. Для выполнения копирования по слову оба источника и адресата должны быть выровнены по словам. Я хочу сделать это. – Praveen

+0

@Praveen: И даже если вы примете жадный подход, проверка должна быть связана с тем, является ли она такой же несоосностью, и в этом случае вы можете исправить ее с помощью начальной 1/2/3-байтной копии. – einpoklum

0

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

1) Оба буфера смещены от четырехбайтовой границы на одну и ту же сумму или оба являются уже на четырехбайтовой границе. (src % 4 == dst % 4) В этом случае копирование первых байтов побайтовое число, тогда использование выравнивания только адреса назначения является хорошим.

2) Буферы не находятся на одной границе. (src % 4 != dst % 4) В этом случае для того, чтобы скопировать из одного выравнивания в другое, одно слово в то время, процессор должен следовать процесс, подобный приведенному ниже:

Load the new word 
Split it into an upper half and lower half. 
Shift the upper half down 
Shift the lower half up 
Add the upper half the previous lower half. 
Store the combined copy to memory 
Repeat 

Я не уверен, что это будет быстрее, чем просто копирование побайтно. Halfword-by-halfword может быть быстрее, если ваша процессорная архитектура позволяет это, и оба буфера выровнены по полуслову, хотя большинство реализаций memcpy, которые я видел на архитектурах, которые поддерживают загрузку/хранение halfword, уже делают это.