Я модифицирую нейронную сеть RNNLM для изучения языковой модели. Однако, учитывая размер моего корпуса, он работает очень медленно. Я попытался оптимизировать подпрограмму matrix*vector (на которую приходится 63% общего времени для небольшого набора данных (я ожидаю, что на больших наборах будет хуже)). Сейчас я застрял с внутренностями.
for (b=0; b<(to-from)/8; b++)
{
val = _mm256_setzero_ps();
for (a=from2; a<to2; a++)
{
t1 = _mm256_set1_ps (srcvec.ac[a]);
t2 = _mm256_load_ps(&(srcmatrix[a+(b*8+from+0)*matrix_width].weight));
//val =_mm256_fmadd_ps (t1, t2, t3)
t3 = _mm256_mul_ps(t1,t2);
val = _mm256_add_ps (val, t3);
}
t4 = _mm256_load_ps(&(dest.ac[b*8+from+0]));
t4 = _mm256_add_ps(t4,val);
_mm256_store_ps (&(dest.ac[b*8+from+0]), t4);
}
Этот пример аварийно завершает работу:
_mm256_store_ps (&(dest.ac[b*8+from+0]), t4);
Однако, если я перейду на
_mm256_storeu_ps (&(dest.ac[b*8+from+0]), t4);
(с u для невыровненного, я полагаю) все работает как задумано. Мой вопрос: почему load работает (в то время как это не должно, если данные не выровнены), а store - нет. (к тому же оба работают на одном и том же адресе).
dest.ac были выделены с использованием
void *_aligned_calloc(size_t nelem, size_t elsize, size_t alignment=64)
{
size_t max_size = (size_t)-1;
// Watch out for overflow
if(elsize == 0 || nelem >= max_size/elsize)
return NULL;
size_t size = nelem * elsize;
void *memory = _mm_malloc(size+64, alignment);
if(memory != NULL)
memset(memory, 0, size);
return memory;
}
и это не менее 50 элементов. (Кстати, с VS2012 у меня есть недопустимая инструкция для какого-то случайного назначения, поэтому я использую Linux.)
заранее спасибо, Аркантус.
from
? Есть ли шанс, что встроенная функция_mm256_load_ps
на самом деле реализована как 2 128-битные загрузки? - person Come Raczy   schedule 19.05.2015b
на8 * matrix_width
вместо умноженияb * 8
в индексном выражении. gcc кажется плохим в преобразовании циклов, чтобы поддерживать только масштабированную версию счетчика циклов, когда вы не записываете цикл таким образом. - person Peter Cordes   schedule 24.06.2015set1
могут работать медленно. Будьте осторожны с ними. Надеюсь, это компилируется в файлvbroadcastss ymm, [mem]
. Если вы можете организовать свои структуры данных так, чтобы они не нуждались во внутреннем цикле, это может быть быстрее. Простой обмен внутренними/внешними циклами, чтобы одно и то жеsrcvec
использовалось для всех значенийb
, было бы медленнее из-за необходимости собирать несмежные данные изsrcmatrix
.vbroadcastss
составляет 2 мопса и 5 циклов задержки из памяти (на Haswell). На 1 цикл меньше при 128-битном назначении вместо 256. Пропускная способность составляет 1 на цикл (может работать только на порту 5 на SnB/IvB/HSW). - person Peter Cordes   schedule 24.06.2015