.
Собрание интересных и полезных материалов по множеству направлений — без ограничений в темах.
Позвонить: +7 (384) 445-09-33Так сложилось, узким местом во многих компьютерах является интерфейс оперативная память — процессор. Связано это со значительным временем формирования запроса в память и с тем что частота работы памяти ниже частоты процессора. В общем случае на время получения данных из памяти исполнение программы останавливается. Для улучшения ситуации используется специализированная высокоскоростная память – кеш.
При наличии кеша, если процессору требуется обратиться к определенному байту в оперативной памяти, то сначала выбирается область памяти содержащая этот байт (размер области зависит от процессора) в кеш, а затем происходит считывание данных из кеша процессором. Если процессор записывает данные в память, то они сначала попадают в кеш, а затем в оперативную память.
В многоядерной и многопроцессорной системах у каждого ядра или процессора есть свой персональный кеш. В случае модификации данных в кеше одним процессором, изменения должны быть синхронизированы с другими процессорами, использующими пересекающееся адресное пространство. Если изменения происходят часто и области данных сильно пересекаются, то будет падать производительность.
У меня возник вопрос насколько все может быть плохо. Кроме того, интересно было посмотреть как влияет длина данных.
Эксперимент. Для проверки были написаны 2 многопоточных программы на С++ для двух случаев пересечения рабочих областей:
Рабочих нитей – 2, каждая, меняя свои слова, проходит весь массив и, достигнув границы, возвращается к началу и так далее. Каждая из нитей делает по 100 000 000 изменений.
UPD Спасибо mikhanoid за выявленную опечатку в названии CPU. Для тестирования использовалась рабочая станция HP xw4600, CPU Core 2 Quad (Q9300), OS Linux Slamd64 12.1, ядро 2.6.24.5, компилятор gcc 4.2.3. В итоге получалась 64-х битная программа, следовательно любая арифметическая операция для слов длиной 1,4 и 8 байт выполнялась за 1 такт.
Время исполнения измерялось командой time(1), и усреднялось по 5-и экспериментам.
Сначала была написана программа, которая просто инкрементирует слово и кладет его обратно, но оказалось что в случае массива на стеке оптимизация -O2 творит что-то непотребное. Поэтому была написана вторая программа, которая делает с данными что-то более сложное.
Результаты. UPD: Thnx за замечание mt_ и Google Charts за api графиков. Результат в графической форме. Желающие посмотреть цифры, могут промотать дальше.
По оси Y реальное время исполнения программы в секундах. По оси X разрядность слова (парами).
Программа 2 + оптимизация -O2.
Выводы Можно точно сказать, что в случае заведомо не пересекающихся областей работает быстрее, причем значительно. Оптимизация как-то влияет, но тенденция сохраняется.
А вот зависимость от длины слова как-то мало заметна.
UPD Попытка перенести в блог Совершенный код, мне кажется что это самое правильное место.
Результаты в табличной форме. Результаты представлены в секундах.
Программа 1 (общая память). Длина слова 64 32 8 Реальное время 1,297 1,532 0,846 Время польз. режима 2,461 3,049 1,664
Программа 1 (стек) Длина слова 64 32 8 Реальное время 0,453 0,431 0,441 Время польз. режима 0,851 0,842 0,866
Программа 2 (общая память). Длина слова 64 32 8 Реальное время 9,191 9,033 8,921 Время польз. режима 18,365 18,039 17,824
Программа 2 (стек) Длина слова 64 32 8 Реальное время с 8,432 8,412 8,808 Время польз. Режима с 16,843 16,796 17,548
Программа 2 + оптимизация -O2 (общая память). Длина слова 64 32 8 Реальное время 4,247 4,380 3,473 Время польз. режима 8,415 8,960 6,781
Программа 2 + оптимизация -O2 (стек) Длина слова 64 32 8 Реальное время 3,282 3,718 3,308 Время польз. режима 6,550 7,384 5,565
Исходный код.
Программа 1.
#include <stdio.h> #include <stdlib.h>
#define TBYTES 1024 // #define TOTAL 2 // определяет тип слова u_int8_t u_int32_t u_int64_t #define MTYPE u_int8_t // #define MAXAR TBYTES/ sizeof (MTYPE) #define DOIT 100000000
pthread_mutex_t mux = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; int workers = 2;
// Определяет используется ли общая память //#define SHARED 1
void * runner( void * args) // pthread_mutex_lock(&mux); -- workers; pthread_mutex_unlock(&mux); pthread_cond_broadcast(&cond); // return 0; >;
int main() ; // * This source code was highlighted with Source Code Highlighter .
Программа 2.
#include <stdio.h> #include <stdlib.h>
#define TBYTES 1024 // #define TOTAL 2 // определяет тип слова u_int8_t u_int32_t u_int64_t #define MTYPE u_int64_t // #define MAXAR TBYTES/ sizeof (MTYPE) //#define DOIT 100000000 * (sizeof(u_int64_t) / sizeof(MTYPE)) #define DOIT 100000000
pthread_mutex_t mux = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; int workers = 2;
template<typename RTYPE, int TLEN> RTYPE scramble(u_int16_t *seed, RTYPE a) 1) &0x1); mask = mask & 0x1; *seed = (mask << 15) | (*seed >> 1); // a = a ^ ((RTYPE)mask << d); > // return a; >;
// Определяет используется ли общая память //#define SHARED 1
void * runner( void * args) (&seed, data); #else data = array1[index]; array1[index] = scramble<MTYPE, 8* sizeof (MTYPE)>(&seed, data); #endif // index += TOTAL; > // pthread_mutex_lock(&mux); -- workers; pthread_mutex_unlock(&mux); pthread_cond_broadcast(&cond); // return 0; >;
int main() ; // * This source code was highlighted with Source Code Highlighter .
Мы предоставляем площадку для быстрого доступа к разнообразной информации. Подборки формируются без привязки к узким тематикам, чтобы читатель всегда находил что-то интересное или полезное для себя.
Краткие сводки по темам, вызывающим наибольший интерес среди пользователей.
Тексты на повседневные, бытовые, региональные и популярные темы.
Собранные по схожести темы статьи и материалы разного характера.
Доступ к ранее опубликованным материалам и тематическим блокам.
📍 г. Кемерово, ул. Полезная, д. 21, офис 410
☎ +7 (384) 445-09-33
📧 info@site.ru
🕓 Приём писем: ежедневно, 08:00 – 22:00
Контент, размещённый на сайте, поступает из общедоступных источников и обрабатывается автоматически. Администрация не участвует в создании и проверке опубликованных материалов.
При наличии претензий по поводу авторских прав, обратитесь к нам по контактному адресу — мы оперативно отреагируем на обоснованное обращение.
Сайт не зарегистрирован как СМИ и не несёт ответственности за точность информации.