2016-11-16 2 views
0

Я пытаюсь использовать Intel Intrinsics для быстрой работы с массивом float. Кажется, что эти операции работают нормально; однако, когда я пытаюсь получить результат операции в стандартную переменную C, я получаю SEGFAULT. Если я прокомментирую указанную строку ниже, программа запустится. Если я сохраню результат указанной строки, но никак не буду манипулировать ею, программа будет работать нормально. Только когда я пытаюсь (каким-либо образом) взаимодействовать с результатом _mm_cvtss_f32(C), что моя программа вылетает. Есть идеи?SSE SIMD Сегментация Неисправность при использовании результирующего float

float proc(float *a, float *b, int n, int c, int width) { 
    // Operation: SUM: (A - B)^2 
    __m128 A, B, C; 
    float total = 0; 
    for (int d = 0, k = 0; k < c; d += width, k++) { 
     for (int i = 0; i < n/4 * 4; i += 4) { 
      A = _mm_load_ps(&a[i + d]); 
      B = _mm_load_ps(&b[i + d]); 
      C = _mm_sub_ps(A, B); 
      C = _mm_mul_ps(C, C); 
      C = _mm_hadd_ps(C, C); 
      C = _mm_hadd_ps(C, C); 
      total += _mm_cvtss_f32(C); // SEGFAULT HERE 
     } 
     for (int i = n/4 * 4; i < n; i++) { 
      int diff = a[i + d] - b[i + d]; 
      total += diff * diff; 
     } 
    } 
    return total; 
} 
+4

Вы действительно уверены, что ваша программа действительно вылетает из инструкции, которую вы указали, или компилятор просто оптимизирует остальную часть цикла, если вы удалите строку '_mm_cvtss_f32()' (у нее нет других видимых побочных эффектов) ? Потенциальными причинами отказа были бы неправильное выравнивание массивов 'a' и' b', поскольку вы используете согласованные инструкции загрузки. Вы уверены, что они выровнены по 16 байт? На современном оборудовании Intel очень мало разницы в производительности между 16-байтовыми выровненными и невыровненными нагрузками («movaps» имеет более короткую командную кодировку, чем «movups», но это о ней). –

+1

Спасибо, я изменил 'load' на' loadu', и теперь он работает! – Simon

+1

@JasonR: Их кодировка имеет одинаковую длину. http://www.felixcloutier.com/x86/MOVAPS.html против http://www.felixcloutier.com/x86/MOVUPS.html. Если вы сравнивали разборку, у одного из них был префикс REX или другой режим адресации? Во всяком случае, они выполняются идентично, когда данные выравниваются во время выполнения, но когда пропускная способность чтения кэша L1 является узким местом, выровненные нагрузки имеют преимущество. Это хорошая идея, чтобы ваши данные были выровнены, когда это было дешево. –

ответ

0

Вы уверены, что ваша программа на самом деле происходит сбой в инструкции вы цитируемой, или компилятор просто оптимизировать остальную часть петли прочь, если вы удалите строку _mm_cvtss_f32() (она не имеет какой-либо другой видимую сторону последствия)? Потенциальными причинами сбоя было бы неправильное выравнивание массивов a и b, так как вы используете согласованные инструкции загрузки. Вы уверены, что они выровнены по 16 байт? На современном оборудовании Intel очень мало разницы в производительности между 16-байтовыми выровненными и невыровненными нагрузками (см. Комментарии к вышеизложенному вопросу для обсуждения проблемы).

В своем первоначальном комментарии я упомянул, что movaps имеет более короткое кодирование, чем movups. Неправильное использование. Я думал вместо movaps по сравнению с movapd, которые выполняют одну и ту же передачу памяти, только они помечены как данные для одной и двух точности, соответственно. На практике они делают то же самое, но movaps имеет более короткое кодирование.

Смежные вопросы