У меня есть вопрос о дублировании строки с нулем в конце:
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 миллисекунды
Замена библиотечных функций своими собственными часто приводит к снижению производительности.
memcpy
представляет собой очень фундаментальную операцию памяти. Из-за этого это очень оптимизировано его авторами. В отличие от «наивной» реализации, версия библиотеки перемещается более чем на один байт за раз, когда это возможно, и использует аппаратную помощь на платформах, где она доступна.
Более того, сам компилятор «знает» о внутренней работе memcpy
и другие библиотечные функции, и это может полностью оптимизировать их для случаев, когда длина известна во время компиляции.
Замечания: Ваша реализация имеет семантику strcpy
не memcpy
,
… оба эти пути одинаковы!
Нет, они не
memcpy()
не проверяет каждый символ на наличие '\0'
или нет.Маловероятно, что ваш подход может быть сделан быстрее, чем memcpy()
,
То, что вы не использовали указатели, и сравнение того, что вы делаете (strcpy) с memcpy, ясно показывает, что вы новичок, и, как уже говорили все остальные, трудно перехитрить опытного программиста, подобного тем, кто кодировал вашу библиотеку.
Но я дам вам несколько советов по оптимизации вашего кода.
Я быстро взглянул на реализацию стандартной библиотеки Microsoft C (дублированную C Runtime Library), и они делают это в сборке, что быстрее, чем в C. Так что это одно из соображений скорости.
В большинстве 32-битных архитектур с 32-битными шинами ЦП может извлекать 32 бита информации из памяти за один запрос в память (при условии, что данные правильно выровнены), но даже если вам нужно 16 или 8 бит, ему все равно нужны сделать этот 1 запрос. Так что работа с размером слова вашей машины, вероятно, даст вам некоторую скорость.
Наконец, я хочу обратить ваше внимание на SIMD. Если ваш процессор обеспечивает его, вы можете использовать его и получить дополнительную скорость. Снова MSCRT имеет несколько опций оптимизации SSE2.
Раньше время от времени мне приходилось писать код, который превосходил мою библиотечную реализацию, потому что у меня была конкретная потребность или особый тип данных, которые я мог бы оптимизировать, и хотя они могли бы иметь определенную образовательную ценность, если в этом нет особой необходимости, ваше время лучше потратить на ваш реальный код, чем потратить на повторную реализацию ваших библиотечных функций.