Собственный сбой из-за невыровненного доступа с MSVC14 и AVX - PullRequest
0 голосов
/ 06 июня 2018

У меня есть следующий фрагмент кода, который может использовать SIMD.Он прекрасно работает в Linux + GCC, но я уже некоторое время бьюсь головой о стену, потому что он падает, когда я строю его с MSVC с включенным AVX.

template <>
void NewtonRaphson<double, InstructionSet::AVX>::initializeLu(const int elements)
{
    std::cerr << "EDE " << EIGEN_DEFAULT_ALIGN_BYTES << "\n";
    std::cerr << "Allocations are already aligned = " << EIGEN_MALLOC_ALREADY_ALIGNED << "\n";

    m_luCalc = new Eigen::PartialPivLU<SolverMatrix<double>>(elements);
}

template <>
typename NewtonRaphson<double, InstructionSet::AVX>::TX const & NewtonRaphson<double, InstructionSet::FMA3>::ASolve()
{
    m_iteration = 0;
    m_stuckCounter = 0;

    AInit();

    // DOIT

    std::cerr << "EDE WKR" << EIGEN_DEFAULT_ALIGN_BYTES << "\n";
    std::cerr << "...WKR Allocations are already aligned = " << EIGEN_MALLOC_ALREADY_ALIGNED << "\n";

    while (true)
    {
        // !2
        ACalculateF(m_f, *m_px);
        ACalculateJ(m_j, *m_px);

        ZCalculateMeasures(m_f, m_fMin, m_fMax);
        ZCalculateMeasures(m_dx, m_dxMin, m_dxMax);                                  // 1

        ZCheckStatus();

        if (m_status != Status::CONTINUE)
            return *m_px;

        this->m_iteration++;

        m_luCalc->compute(m_j);
        m_dx = m_luCalc->solve(m_f);

        *m_px -= m_dx;
    };

    return *m_px;
}

Код находится в отдельном месте.cpp файл, который скомпилирован с соответствующими флагами оптимизации.Сбой происходит в начале функции PartialPivLU :: compute ().Беглый взгляд на сборку, сгенерированную MSVC для функции-нарушителя, показывает следующее:

5D43D243  jle         Eigen::PartialPivLU<Eigen::Matrix<double,-1,-1,0,-1,-1> >::compute<Eigen::Map<Eigen::Matrix<double,-1,-1,0,-1,-1>,32,Eigen::Stride<0,0> > >+0E9h (5D43D269h)  
5D43D245  nop         word ptr [eax+eax]  
5D43D250  mov         eax,dword ptr [ebp-1Ch]  
5D43D253  vmovupd     ymm0,ymmword ptr [eax+ecx*8]  
5D43D258  vmovapd     ymmword ptr [edi+ecx*8],ymm0 

Сбой происходит по команде vmovapd, которая пытается прочитать 16-байтовый выровненный адрес.EIGEN_DEFAULT_ALIGN_BYTES установлен на 32, а EIGEN_MALLOC_ALREADY_ALIGNED равен 0. Этот код работает нормально, когда я настраиваю оптимизацию SIMD на SSE2.

Есть ли что-то, чего мне не хватает для достижения правильного выравнивания с MSVC?

1 Ответ

0 голосов
/ 06 июня 2018

Хорошо, я думаю, что дошел до сути.Мой код определяет, какие наборы команд ЦП доступны во время выполнения, и динамически распределяет выполнение по функциям, которые используют доступные наборы инструкций.Я переместил части своего кода, которые используют разные инструкции SIMD, в разные TU, чтобы сделать это возможным.Это работает нормально, пока я не решил включить векторизацию в частях кода, которые напрямую используют Eigen.Хотя каждый TU снова включает в себя все Eigen, поэтому его внутренние значения устанавливаются соответствующим образом, распределители Eigen не шаблонируются и определяются как встроенные.Поэтому компилятор объединяет все определения handmade_aligned_malloc в одну функцию, даже если они на самом деле не делают одно и то же, потому что значение EIGEN_DEFAULT_ALIGN_BYTES отличается в каждом TU в зависимости от того, какие флаги компилятора установлены.То, что он работает с GCC под Linux, возможно, случайно.Хотя мне все еще нужно найти правильное решение для этого, я считаю, что это отвечает на вопрос о том, что стало причиной аварии.

...