Кэш -линии, ложное обмен и выравниваниеC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Кэш -линии, ложное обмен и выравнивание

Сообщение Anonymous »

Я написал следующую короткую программу C ++, чтобы воспроизвести эффект ложного обмена, как описано Herb Sutter: < /p>

, скажем, мы хотим выполнить общее количество целостных операций рабочей нагрузки, и мы хотим, чтобы они были одинаково распространены по числу (параллельно) потоков. Для целей этого теста каждый поток будет увеличивать свою собственную выделенную переменную из массива целых чисел, поэтому процесс может быть идеально параллелизируемым. < /P>

void thread_func(int* ptr)
{
for (unsigned i = 0; i < WORKLOAD / PARALLEL; ++i)
{
(*ptr)++;
}
}

int main()
{
int arr[PARALLEL * PADDING];
thread threads[PARALLEL];

for (unsigned i = 0; i < PARALLEL; ++i)
{
threads = thread(thread_func, &(arr[i * PADDING]));
}
for (auto& th : threads)
{
th.join();
}
return 0;
}
< /code>

Я думаю, что идея легко понять. Если вы установили < /p>

#define PADDING 16
< /code>

Каждый поток будет работать на отдельной линии кэша (при условии, что длина линии кэша составляет 64 байта). Таким образом, результатом будет линейное увеличение ускорения до параллелей> # ядра. Если, с другой стороны, накладка установлена ​​на любое значение ниже 16, нужно столкнуться с серьезным конфликтом, поскольку, по крайней мере, два потока в настоящее время могут работать на одной и той же линии кэша, которая, однако, защищена встроенным аппаратным мутекс. Мы ожидаем, что наше ускорение не только будет сублинейным в этом случае, но даже будет всегда

Теперь мои первые попытки почти удовлетворили эти ожидания, однако минимальное значение прокладки, необходимое для того, чтобы избежать ложного обмена, составляли около 8, а не 16. Я был довольно озадачен в течение около полчаса, пока я не пришел к очевидному выводу, что нет гарантии, что моя массива будет точно выровнен в начале линии Cache. Фактическое выравнивание может варьироваться в зависимости от многих условий, включая размер массива. < /p>

В этом примере, конечно, нам нет необходимости, чтобы массив выровнен особым образом, потому что мы можем просто оставить набивку в 16 лет, и все работает нормально. Но можно представить случаи, когда это имеет значение, независимо от того, выровнена ли определенная структура с линией кеша или нет. Следовательно, я добавил несколько строк кода, чтобы получить некоторую информацию о фактическом выравнивании моего массива. < /P>

int main()
{
int arr[PARALLEL * 16];
thread threads[PARALLEL];
int offset = 0;

while (reinterpret_cast(&arr[offset]) % 64) ++offset;
for (unsigned i = 0; i < PARALLEL; ++i)
{
threads = thread(thread_func, &(arr[i * 16 + offset]));
}
for (auto& th : threads)
{
th.join();
}
return 0;
}
< /code>

Несмотря на то, что это решение получило хорошо для меня в этом случае, я не уверен, что это будет хорошим подходом в целом. Итак, вот мой вопрос: < /p>

Есть ли какой -либо общий способ, чтобы объекты в памяти выровнены по линиям кэша, отличных от того, что я сделал в приведенном выше примере?>

Подробнее здесь: https://stackoverflow.com/questions/182 ... -alignment
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»