более быстрый способ, чем memcpy, чтобы скопировать строку с нулем в конце

У меня есть вопрос о дублировании строки с нулем в конце:

const char * str = "Hello World !";
size_t getSize = strlen(str);
char * temp = new char[getSize + 1];

… я знаю, что могу использовать эту функцию

memcpy(temp, str, getSize);

но я хочу использовать свою собственную функцию копирования, которая имеет такое действие

int Count = 0;
while (str[Count] != '\0') {
temp[Count] = str[Count];
Count++;
}

оба пути верны и успешны. теперь я хочу проверить это на 10 миллионов раз и для memcpy сделать это действие

const char * str = "Hello World !";
size_t getSize = strlen(str);
for (size_t i = 0; i < 10000000; i++) {
char * temp = new char[getSize + 1];
memcpy(temp, str, getSize);
}

и это для меня

    const char * str = "Hello World !";
size_t getSize = strlen(str);
for (size_t i = 0; i < 10000000; i++) {
char * temp = new char[getSize + 1];
int Count = 0;
while (str[Count] != '\0') {
temp[Count] = str[Count];
Count++;
}
}

первый процесс сделан в 420 миллисекунд а второй сделано в 650 миллисекунд
… Зачем? оба эти пути одинаковы! я хочу использовать свою собственную функцию, а не memcpy. Есть ли способ сделать мой собственный путь быстрее (быстро, как memcpy быстро или, возможно, быстрее)? Как я могу обновить свой собственный способ (пока), чтобы сделать его быстрее или равным с memcpy?

полный источник

int main() {

const char * str = "Hello world !";
size_t getSize = strlen(str);

auto start_t = chrono::high_resolution_clock::now();
for (size_t i = 0; i < 10000000; i++) {
char * temp = new char[getSize + 1];
memcpy(temp, str, getSize);
}
cout << chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_t).count() << " milliseconds\n";start_t = chrono::high_resolution_clock::now();
for (size_t i = 0; i < 10000000; i++) {
char * temp = new char[getSize + 1];
int done = 0;
while (str[done] != '\0') {
temp[done] = str[done];
done++;
}
}
cout << chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start_t).count() << " milliseconds\n";

return 0;
}

Результаты:

482 миллисекунды
654 миллисекунды

-1

Решение

Замена библиотечных функций своими собственными часто приводит к снижению производительности.

memcpy представляет собой очень фундаментальную операцию памяти. Из-за этого это очень оптимизировано его авторами. В отличие от «наивной» реализации, версия библиотеки перемещается более чем на один байт за раз, когда это возможно, и использует аппаратную помощь на платформах, где она доступна.

Более того, сам компилятор «знает» о внутренней работе memcpy и другие библиотечные функции, и это может полностью оптимизировать их для случаев, когда длина известна во время компиляции.

Замечания: Ваша реализация имеет семантику strcpyне memcpy,

3

Другие решения

… оба эти пути одинаковы!

Нет, они не

  1. memcpy() не проверяет каждый символ на наличие '\0' или нет.
  2. Реализаторы могут выполнить больше оптимизаций, чем вы наивный подход

Маловероятно, что ваш подход может быть сделан быстрее, чем memcpy(),

1

То, что вы не использовали указатели, и сравнение того, что вы делаете (strcpy) с memcpy, ясно показывает, что вы новичок, и, как уже говорили все остальные, трудно перехитрить опытного программиста, подобного тем, кто кодировал вашу библиотеку.

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

В большинстве 32-битных архитектур с 32-битными шинами ЦП может извлекать 32 бита информации из памяти за один запрос в память (при условии, что данные правильно выровнены), но даже если вам нужно 16 или 8 бит, ему все равно нужны сделать этот 1 запрос. Так что работа с размером слова вашей машины, вероятно, даст вам некоторую скорость.

Наконец, я хочу обратить ваше внимание на SIMD. Если ваш процессор обеспечивает его, вы можете использовать его и получить дополнительную скорость. Снова MSCRT имеет несколько опций оптимизации SSE2.

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

0
По вопросам рекламы [email protected]