Нехватка регистра с использованием встроенных функций SSE

В этом посте SSE загрузка / хранение транзакций в памяти Я спросил о различиях между явными транзакциями в памяти регистра и промежуточными указателями. На практике промежуточные указатели показали немного более высокую производительность, однако неясно, что такое промежуточный указатель с точки зрения аппаратного обеспечения? Если указатель был создан, означает ли это, что некоторые регистры также заняты, или вызов регистра происходит во время некоторой операции SSE (например, _mm_mul)?

Давайте рассмотрим пример:

struct sse_simple
{
sse_simple(unsigned int InputLength):
Len(InputLength/4),
input1((float*)_mm_malloc((float *)_mm_malloc(cast_sz*sizeof(float), 16))),
input2((float*)_mm_malloc((float *)_mm_malloc(cast_sz*sizeof(float), 16))),
output((float*)_mm_malloc((float *)_mm_malloc(cast_sz*sizeof(float), 16))),
inp1_sse(reinterpret_cast<__m128*>(input1)),
inp1_sse(reinterpret_cast<__m128*>(input2)),
output_sse(reinterpret_cast<__m128*>(output))
{}

~sse_simple()
{
_mm_free(input1);
_mm_free(input2);
_mm_free(output);
}

void func()
{
for(auto i=0; i<Len; ++i)
output_sse[i] = _mm_mul(inp1_sse[i], inp2_sse[i]);
}

float *input1;
float *input2;
float *output;

__m128 *inp1_sse;
__m128 *inp2_sse;
__m128 *output_sse;

unsigned int Len;
};

В приведенном выше примере промежуточные указатели inp1_sse, inp2_sse и output_sse создаются один раз в конструкторе. Если я реплицирую большое количество объектов sse_simple (например, 50 000 и более), может ли это привести к нехватке регистров?

0

Решение

Прежде всего, регистры — это небольшие запоминающие устройства, которые близки (что означает, что доступ очень быстрый) к вычислительным единицам. Компилятор старается максимально использовать их для ускорения вычислений, но когда это невозможно, он использует память. Поскольку объем памяти, хранящейся в регистре, невелик, обычно регистры используются только как временные данные во время вычислений. Большую часть времени все заканчивается хранением в памяти, за исключением временной переменной, такой как индексы цикла … Так что нехватка регистров только замедляет вычисления.

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

Итак, в вашем примере массивы деревьев будут храниться в памяти и строка

output_sse[i] = _mm_mul(inp1_sse[i], inp2_sse[i]);

компилируется как:

movaps -0x30(%rbp),%xmm0    # load inp1_sse[i] in register %xmm0
movaps -0x20(%rbp),%xmm1    # load inp2_sse[i] in register %xmm1
mulps  %xmm1,%xmm0          # perform the multiplication the result is stored in %xmm0
movaps %xmm0,(%rdx)         # store the result in memory

Как вы можете видеть, указатель хранится с использованием регистров %rbp а также %rdx,

2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector