Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.90/20: Рейтинг темы: голосов - 20, средняя оценка - 4.90
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81

Скорость выполнения функции в 2-ух вариантах

26.08.2021, 23:27. Показов 4453. Ответов 33
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Функция a_IsFindForbWord() выполняется в несколько раз быстрее, чем b_IsFindForbWord():

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool a_IsFindForbWord()
{
    char str[] = "философия знак новое!территория субъект стих.забота дождь политика доля.";
 
    char *piece = strtok(str, ". :)(;?,!*\"'-+=");
 
    while (piece != nullptr)
    {
        for (const auto &element : forb_words)
        {
            if (strcmp(piece, element.c_str()) == 0)
            {
                return true;
            }
        }
    
        piece = strtok(0, ". :)(;?,!*\"'-+=");
    }
 
    return false;
}


Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
bool b_IsFindForbWord()
{
    std::string str_source = "философия знак новое!территория субъект стих.забота дождь политика доля.";
 
    std::regex words_regex("[^\\. :)(;?,!*\"'-+=]+");
 
    auto begin = std::sregex_iterator(str_source.begin(), str_source.end(), words_regex);
    auto end = std::sregex_iterator();
 
    for (auto i = begin; i != end; ++i)
    {
        std::smatch match = *i;
 
        std::string word_from_source = match.str();
 
        //printf("word_from_source = '%s'\n", word_from_source.c_str());
 
        for (const auto &element : forb_words)
        {
            if (word_from_source == element.c_str())
            {
                return true;
            }
        }
    }
 
    return false;
}


Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main()
{
    setlocale(LC_ALL, "ru");
 
    // Загрузка слов. Записывает в вектор строк forb_words слова (кол-во ~ 5000) из файла .ini
    LoadingForbiddenWords();
 
    // Вычисления
    unsigned int t1 = GetTickCount();
 
    for (int i = 0; i < 100000; i++)
    {
        a_IsFindForbWord();
        // b_IsFindForbWord();
    }
 
    unsigned int t2 = GetTickCount();
 
    printf("Время работы программы = %d", t2 - t1);
 
    _getch();
 
    return 0;
}


Результат теста:
a_IsFindForbWord(): 10203 (10 секунд)
b_IsFindForbWord(): 67596 (67 секунд)

Мне бы хотелось оставить ф-ию b_IsFindForbWord() для своей программы, но не могу понять - почему она такая медленная? Почитал форум немного и наткнулся, что как-то тормозит цикл где regex_iterator - Медленная работа regex (1-ый пост в конце). Как быть?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.08.2021, 23:27
Ответы с готовыми решениями:

Скорость выполнения функции
У меня в классе Resp() есть функция H_c() которая скачивает с некого сайта каптчу и распознает ее. Я сделал так: public function...

Скорость выполнения функции (IndexOf, if)
Здравствуйте! Подскажите пожалуйста, что экономичней использовать в программе: &quot;if&quot; или &quot;IndexOf&quot;, и на сколько? И...

Уменьшить время выполнения работы программы, увеличить скорость выполнения
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace...

33
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
29.09.2021, 15:50
Студворк — интернет-сервис помощи студентам
ну_ты_ххх_ххх_красавец, ваших разделителей здесь нет, разделить похабщину можно любым символом.
Вы слишком самоуверены, видимо ваша игра детская и хватит и прямого фильтра

Добавлено через 1 минуту
leo7755, кстати цитировать нецензур было не обязательно!
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
29.09.2021, 16:40  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
ну_ты_ххх_ххх_красавец, ваших разделителей здесь нет
ну добавлю, и тильды нет)))
Игра детская, SA-MP по сети (GTA SA), поэтому мне хватит того, что есть)
А вот по поводу map интересно. я занёс в vector слова - разве это не правильно?
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
29.09.2021, 16:46
Лучший ответ Сообщение было отмечено leo7755 как решение

Решение

Цитата Сообщение от leo7755 Посмотреть сообщение
А вот по поводу map интересно. я занёс в vector слова - разве это не правильно?
тут не стоит вопрос в правильности. Слова в векторе вполне "правильно" лежат. )
Вопрос стоит в быстродействии. А значит способ хранения слов (в std::vector) выбран неправильный (не эффективный).
Доступ к слову по ключу map или set (в данном случае предпочтительно использовать set), намного быстрей , чем проходить весь вектор(дин. массив).

Почитайте про хеш функции и деревья, возможно это прояснит ситуацию.
1
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
29.09.2021, 17:03  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
Вопрос стоит в быстродействии. А значит способ хранения слов (в std::vector) выбран неправильный (не эффективный).
Доступ к слову по ключу map или set (в данном случае предпочтительно использовать set), намного быстрей , чем проходить весь вектор(дин. массив).
я попробую поработать с set. переделаю функцию и замерю скорость
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
01.10.2021, 02:43  [ТС]
SmallEvil,
Дело обстоит так, что вместо vector применил контейнер set, а вместо регулярных - boost::split

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#define _CRT_SECURE_NO_WARNINGS
 
 
 
#include <conio.h>
#include <iostream>
#include <fstream>
//#include <iterator>
//#include <string>
#include <regex>
//#include <fstream>
#include <windows.h>
#include <vector>
#include <set>
//#include <map>
//#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>
 
 
 
static std::set<std::string> forb_words;
 
void LoadingForbiddenWords()
{
    char char_path[MAX_PATH];
    GetModuleFileNameA(0, char_path, sizeof(char_path) / sizeof(char_path[0]));
 
    std::string str_path = char_path;
    std::string path_rezult = regex_replace(str_path, std::regex("[A-Za-z0-9]+.exe"), "chat_5000.ini");
 
    std::ifstream handle;
    handle.open(path_rezult);
 
    if (handle)
    {
        forb_words.clear();
 
        std::string source;
 
        while (!handle.eof())
        {
            getline(handle, source);
 
            if (source[0] == 0 || source[0] == '#' || source[0] == ';'
                || (source[0] == '/' && source[1] == '/'))
            {
                continue;
            }
 
            int pos = source.find("=");
 
            std::string sub = source.substr(pos + 1);
 
            sub = regex_replace(sub, std::regex(" |\t"), "");
 
            forb_words.insert(sub);
        }
    }
    handle.close();
}
 
/************************************************************************/
/* strtok                                                               */
/************************************************************************/
 
static char ch_source[] = "философия знак новое!территория субъект стих.забота дождь политика доля.";
 
bool a_IsFindForbWord()
{
    char *piece = strtok(ch_source, ". :)(;?,!*\"'-+=");
 
    while (piece != nullptr)
    {
        for (const auto &element : forb_words)
        {
            if (strcmp(piece, element.c_str()) == 0)
            {
                return true;
            }
        }
 
        piece = strtok(0, ". :)(;?,!*\"'-+=");
    }
 
    return false;
}
 
/************************************************************************/
/* boost::split                                                         */
/************************************************************************/
 
static std::string str_source   =   "философия знак новое!территория субъект стих.забота дождь политика доля.";
static std::vector<std::string>     words_split;
 
bool b_IsFindForbWord()
{
    boost::split(words_split, str_source, boost::is_any_of(". :)(;?,!*\"'-+="));
 
    for (auto it = words_split.cbegin(), end = words_split.cend(); end != it; ++it)
    {
        const std::string word = *it;
 
        for (const auto &element : forb_words)
        {
            if (strcmp(word.c_str(), element.c_str()) == 0)
            {
                return true;
            }
        }
    }
 
    return false;
}
 
int main()
{
    setlocale(LC_ALL, "ru");
 
 
 
    LoadingForbiddenWords();
 
    //if (b_IsFindForbWord())
    //{
    //  printf("найдено слово");
    //}
    //else
    //{
    //  printf("НЕ найдено слов");
    //}
 
    unsigned int t1 = GetTickCount();
 
    for (int i = 0; i < 100000; i++)
    {
        // a_IsFindForbWord();
        b_IsFindForbWord();
    }
 
    unsigned int t2 = GetTickCount();
 
    printf("Время работы программы = %d", t2 - t1);
 
 
 
    _getch();
 
    return 0;
}

Результат теста обрадовал. Ну явно побыстрее, чем было (~ на 20 сек.):

a_IsFindForbWord(): 6365 (6 секунд)
b_IsFindForbWord(): 48937 (48 секунд)

Имеются ли недочёты в b_IsFindForbWord()?
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
01.10.2021, 08:39
Лучший ответ Сообщение было отмечено leo7755 как решение

Решение

Цитата Сообщение от leo7755 Посмотреть сообщение
Имеются ли недочёты в b_IsFindForbWord()?
Ты не пользуешься преимуществами std::set. Вместо всего внутреннего цикла можно бы было просто написать:
C++
1
2
if (forb_words.count(word))
    return true;
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
02.10.2021, 02:21  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static std::string str_source =     "философия знак новое!территория субъект стих.забота дождь политика доля.";
static std::vector<std::string>     words_split;
 
bool b_IsFindForbWord()
{
    boost::split(words_split, str_source, boost::is_any_of(". :)(;?,!*\"'-+="));
 
    for (auto it = words_split.cbegin(), end = words_split.cend(); end != it; ++it)
    {
        if (forb_words.count(std::string(*it)))
        {
            return true;
        }
    }
 
    return false;
}
100 тысяч итераций:
a_IsFindForbWord() : 62 млс.
b_IsFindForbWord() : 843 млс.

1 млн. итераций:
a_IsFindForbWord() : 390 млс.
b_IsFindForbWord() : 8096 млс.

nonedark2008, не поверишь - не зря использовал метод count. Дополнительно поменял set на unordered_set. С ним даже быстрее вышло. Данные в отсортированном виде мне не нужны. Но осталось пару вопросов:

1) std::vector<std::string> words_split обязательно выносить на функцию?
2) можно ли оставить условие в таком виде?
C++
1
2
3
4
5
if (forb_words.count(std::string(*it)))
 
//или так?
const std::string word = *it;
if (forb_words.count(word))
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
02.10.2021, 03:15
C++
1
if (forb_words.count(*it))
вот так, по итератору уже строка находится.

Цитата Сообщение от leo7755 Посмотреть сообщение
std::vector<std::string> words_split обязательно выносить на функцию?
Тут я не совсем понял.
Разделяются слова сообщения, сообщение каждый раз разное, значит и набор слов тоже.
Значит это данные функции и желательно что б они были внутри по всей логике.
А почему words_split объявлена как static ?
И саму строку(сообщение) передавай в функцию по ссылке, много не потеряешь.

Добавлено через 6 минут
Странно но я не вижу твое отфильтрованное сообщение

Добавлено через 4 минуты
Или решил всЁ сообщение блочить ? ))

Добавлено через 13 секунд
Или решил всЁ сообщение блочить ? ))
1
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
02.10.2021, 03:15
Или решил всЁ сообщение блочить ? ))
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
02.10.2021, 05:25  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
А почему words_split объявлена как static ?
Она же глобальной будет, если затереть static. А так только в этом файле доступна.

Цитата Сообщение от SmallEvil Посмотреть сообщение
в функцию по ссылке
да?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
bool b_IsFindForbWord(const std::string &source)
{
    boost::split(words_split, source, boost::...));
}
 
if (b_IsFindForbWord(str_source))
{
    printf("найдено слово");
}
else
{
    printf("НЕ найдено слов");
}
Цитата Сообщение от SmallEvil Посмотреть сообщение
Странно но я не вижу твое отфильтрованное сообщение
Или решил всЁ сообщение блочить ? ))
Я тоже не понял о чём ты)))
Принцип работы функции такой. Игрок пишет сообщение в чат. Это сообщение проверяется через IsFindForbWord. Строка разделяется на слова*. Далее производится поиск первого встречающегося запрещённого слова из словаря forb_words. И если слово найдено, то можно например блокировать вывод такого сообщения.

* словом считается набор символов (Aa-Zz, Аа-Яя), которые с одной или с двух сторон разделяются некоторыми символами-разделителями
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
03.10.2021, 16:49  [ТС]
Цитата Сообщение от leo7755 Посмотреть сообщение
глобальной
вернее она останится глобальной, но в пределах данного файла
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
03.10.2021, 16:59
Жесткий фильтр, одно слово не то и бан всему сообщению )
И можно не понять почему, если произойдет ложное срабатывание.

Цитата Сообщение от leo7755 Посмотреть сообщение
вернее она останится глобальной, но в пределах данного файла
Да я понимаю, но зачем она глобальная (words_split)?
Ради прироста пары милисекунд ?
Она же все равно очищается (дожна) и заполняется заново при каждом вызове функции.

Добавлено через 2 минуты
Она часть этой функции, объявить ее static внутри функции еще понятно.

Добавлено через 36 секунд
И то сомнительно.
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
03.10.2021, 17:23  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
Жесткий фильтр, одно слово не то и бан всему сообщению )
Ну можно закрыть звёздочками (само запрещённое слово, т.е. 'ты п*****c') или впускать сообщение, но при этом выдавать автоматически заглушку на n-минут (чтобы игрок не мог пользоваться чатом несколько минут). Такое практикуется же, я видел в разных играх).
Цитата Сообщение от SmallEvil Посмотреть сообщение
Она же все равно очищается (дожна) и заполняется заново при каждом вызове функции.
вот это мне и нужно понять, как её оставить локально или глобально. значит локально
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
03.10.2021, 18:31
Цитата Сообщение от leo7755 Посмотреть сообщение
Ну можно закрыть звёздочками (само запрещённое слово, т.е. 'ты п*****c') или впускать сообщение, но при этом выдавать автоматически заглушку на n-минут (чтобы игрок не мог пользоваться чатом несколько минут). Такое практикуется же, я видел в разных играх).
Тогда подход совсем другой будет, но зато практика уже есть, так что все дело во времени/необходимости.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
03.10.2021, 18:31

Уменьшить время выполнения работы программы, увеличить скорость выполнения
Подскажите, пожалуйста, как можно сократить время при компиляции, нужно не более 1 секунды, при некоторых данных выполняется дольше,...

Написать следующие функции в двух вариантах
char* strstr(char* string1, char* string2) Возвращает указатель на первое вхождение подстроки string2 в строке string1. В случае...

Работа с файлами. Нужно сделать функции сохранения и загрузки данных в двух вариантах: текстовый и бинарный режим
Работа с файлами. Нужно сделать функции сохранения и загрузки данных в двух вариантах: текстовый и бинарный режим. С сохранением вроде...

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

Скорость выполнения
В цикле строка выполняется примерно 10тыс раз, хотелось бы быстрее. // №1 if (this.toString().length &gt; maxLength) maxLength =...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
34
Ответ Создать тему
Новые блоги и статьи
Море в объективе
kumehtar 06.07.2026
Хотел написать много проникновенных слов, но передумал. Оно само - говорит. Кто слышит тот слышит.
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась. Первый вариант. . .
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2. Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru