Nano Hash - криптовалюты, майнинг, программирование

С++ SIMD: сохранить значение uint64_t после побитового и операции

Я пытаюсь сделать побитовое & между элементами двух массивов целых чисел uint64_t, а затем сохранить результат в другом массиве. Это моя программа:

#include <emmintrin.h>
#include <nmmintrin.h>
#include <chrono>


int main()
{

  uint64_t data[200];
  uint64_t data2[200];
  uint64_t data3[200];
  __m128i* ptr = (__m128i*) data;
  __m128i* ptr2 = (__m128i*) data2;
  uint64_t* ptr3 = data3;

  for (int i = 0; i < 100; ++i, ++ptr, ++ptr2, ptr3 += 2)
    _mm_store_ps(ptr3, _mm_and_si128(*ptr, *ptr2));

}

Однако я получаю эту ошибку:

test.cpp:17:50: error: cannot convert ‘uint64_t* {aka long unsigned int*}’ to ‘float*’ for argument ‘1’ to ‘void _mm_store_ps(float*, __m128)’
     _mm_store_ps(ptr3, _mm_and_si128(*ptr, *ptr2));

По какой-то причине компилятор думает, что я копирую в массив с плавающей запятой. Можно ли сделать то, что я пытаюсь сделать с массивами uint64_t?

26.02.2017

  • примечание: это нарушает строгое правило алиасинга; скомпилировать с помощью -fno-strict-aliasing. 26.02.2017
  • @M.M Я скомпилировал вот так gcc -std=c++11 -fno-strict-aliasing test.cpp -o test и не получил предупреждения, как ты скомпилировал? 26.02.2017
  • @M.M, если вы можете дать более безопасный и лучший ответ, я приму ваш ответ 26.02.2017
  • @M.M также другие люди могут извлечь выгоду из вашего понимания 26.02.2017
  • Я не компилировал и у меня нет ответа на пост. Вот почему я разместил комментарий, а не ответ. 26.02.2017
  • @MM Типы векторов SSE объявлены __may_alias__. Так что это должно быть нормально. 27.02.2017

Ответы:


1

Вы можете использовать _mm_store_si128.

Сначала измените указатель ptr3 на

  __m128i* ptr3 = (__m128i*) data3;

а потом

  for (int i = 0; i < 100; ++i, ++ptr, ++ptr2, ++ptr3)
    _mm_store_si128(ptr3, _mm_and_si128(*ptr, *ptr2));
26.02.2017
  • Потрясающий! Спасибо злой Пушин! 26.02.2017

  • 2

    Вы используете операцию с плавающей запятой _mm_store_ps, хотя вы действительно хотите хранить целые числа. Поэтому либо используйте _mm_store_si128, либо приведите результат обратно к uint64_t .

    Вы также должны убедиться, что массивы выровнены по 16 байтам, чтобы можно было использовать выровненные операции загрузки/сохранения, которые будут быстрее.

    #include <emmintrin.h>
    #include <nmmintrin.h>
    #include <chrono>
    
    int main()
    {
      __declspec(align(16)) uint64_t data[200];
      __declspec(align(16)) uint64_t data2[200];
      __declspec(align(16)) uint64_t data3[200];
      __m128i* ptr = (__m128i*) data;
      __m128i* ptr2 = (__m128i*) data2;
      __m128i* ptr3 = (__m128i*) data3;
    
      for (int i = 0; i < 100; ++i, ++ptr, ++ptr2, ++ptr3)
        *ptr3 = _mm_and_si128(*ptr, *ptr2);
    }
    
    26.02.2017
  • Если вы читаете этот туториал, в нем говорится, что мы можем просто выполнять кастинг, нам не нужно загружать, почему вы говорите, что мы должны загружать регистры? 26.02.2017
  • Какой учебник? 26.02.2017
  • извините, я думал, что прикрепил его здесь: felix. abecassis.me/2011/09/cpp-getting-started-with-sse 26.02.2017
  • Вы правы, я только что проверил сгенерированный ассемблерный код. Оказывается, даже _mm_store_si128 не требуется, потому что его сгенерирует компилятор, см. мой обновленный ответ. 26.02.2017
  • Если вы не выровняете данные и оставите загрузку компилятору, он будет использовать невыровненный доступ, что нехорошо. Проверьте выходной узел. Лучше загрузите данные вручную, и вы можете увидеть проблему, когда получите segfault. 26.02.2017
  • вы можете увидеть проблему, когда получите ошибку сегментации. ... или нет. Мой компилятор (msvc++) генерирует невыровненную загрузку/сохранение, даже если я явно использую _mm_load_si128 и _mm_store_si128 для невыровненных данных. 26.02.2017
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..