C - __declspec (поток) переменных производительности - PullRequest
4 голосов
/ 22 февраля 2011

Я работаю над многопоточной реализацией библиотеки. В одном модуле этой библиотеки есть несколько глобальных переменных (очень часто используемых при выполнении программы). Чтобы сделать доступ к этим переменным более безопасным, я объявил их, используя ключевое слово Thread-local storage (TLS) __declspec(thread).

Вот вызов внешней функции библиотеки. Эта функция использует модуль с глобальными переменными:

for(i = 0; i<n_cores; i++)
    hth[i] = (HANDLE)_beginthread((void(*)(void*))MT_Interface_DimenMultiCells,0,(void*)&inputSet[i]);

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

Когда я запускаю программу на процессоре с ядром x8, время, необходимое для завершения операции, не превышает 1/3 времени, необходимого для реализации одного процесса.

Я знаю, что невозможно достичь 1/8 времени, но я подумал, что, по крайней мере, 1/6 пригоден для повторного использования.

Вопрос в том, являются ли эти переменные __declspec (thread) причиной столь плохой производительности?

Заранее спасибо, Г.Б.

Ответы [ 2 ]

6 голосов
/ 22 февраля 2011

Если вы объявите их как __declspec(thread) там, где они ранее были глобальными, то вы изменили смысл программы, а также ее характеристики производительности.

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

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

  1. Передать переменную как параметр, чтобы она находилась в стеке.Быстрый доступ к переменным стека.
  2. Если у вас есть функции, которые много читают и записывают эту переменную, а затем возьмите ее копию в начале функции (в локальную переменную), поработайте над этой локальной переменной,и затем по возвращении запишите его обратно в локальный поток.

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

Вариант 1 в основном сводится к тому, чтобы не использовать глобальные переменные (локальные потоки являются формой глобальных).

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

5 голосов
/ 22 февраля 2011

И ответ таков: вам нужно профилировать приложение, а измерить , где тратится больше всего времени.Если оказывается, что в функциях, которые часто ссылаются на данные TLS, ответом может быть «возможно».

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

Профиль, затем оптимизация.

...