Сообщение Re[19]: C# - from indians by indians от 09.06.2015 10:18
Изменено 09.06.2015 11:23 Sinix
Здравствуйте, alex_public, Вы писали:
_>Скорее всего дело в неверных настройках компилятора C++ — ему не позволена автовекторизация. ) У меня такие цифры (правда компилятор gcc):
Да, с /Qvec-report:2 вывод:
Выше по ветке уже был похожий пример
_>Однако даже и без автовекторизазии на твоих же цифрах видно, что разница между C++ и C# вариантом в 2 раза — это уже убойно. )))
Угу, нынешний JIT на числомолотилки не заточен, это давно известно. Чисто ради интереса: какой фреймворк и x64 или x86 вариант проверялся?
P.S. Разница в 2 раза там из-за проверок на границы массива. Для всего кроме "i=0;i<array.Length" они не убираются.
UPD Не из-за них, протупил. Для варианта с указателями на 7 сложений меньше, т.к. аналог (a[p + x]) вычисляется 1 раз. Вот этот вариант с указателями, но с доступом по индексу не отличается от safe-варианта:
_>Скорее всего дело в неверных настройках компилятора C++ — ему не позволена автовекторизация. ) У меня такие цифры (правда компилятор gcc):
Да, с /Qvec-report:2 вывод:
info C5002: loop not vectorized due to reason '1200'
// Loop contains loop-carried data dependences
Выше по ветке уже был похожий пример
Автор: PM
Дата: 05.06.15
. Компилятор c++ в vs2013 местами не блещет.Дата: 05.06.15
_>Однако даже и без автовекторизазии на твоих же цифрах видно, что разница между C++ и C# вариантом в 2 раза — это уже убойно. )))
Угу, нынешний JIT на числомолотилки не заточен, это давно известно. Чисто ради интереса: какой фреймворк и x64 или x86 вариант проверялся?
P.S. Разница в 2 раза там из-за проверок на границы массива. Для всего кроме "i=0;i<array.Length" они не убираются.
UPD Не из-за них, протупил. Для варианта с указателями на 7 сложений меньше, т.к. аналог (a[p + x]) вычисляется 1 раз. Вот этот вариант с указателями, но с доступом по индексу не отличается от safe-варианта:
unsafe static void AtoB(int[] image, int[] buf, int height)
{
int width = image.Length / height;
fixed (int* a = image, b = buf)
{
for (int y = 1; y < height - 1; y++)
{
var p = width * y;
for (int x = 1; x < width - 1; x++)
{
var idx = p + x;
if (a[idx] != 0xffffff)
{
b[idx] = (
a[idx - width] + a[idx - 1] +
a[idx - width - 1] + a[idx - width + 1] +
a[idx + width - 1] + a[idx + width] +
a[idx + 1] + a[idx + width + 1]) >> 3;
}
}
}
}
}
Re[19]: C# - from indians by indians
Здравствуйте, alex_public, Вы писали:
_>Скорее всего дело в неверных настройках компилятора C++ — ему не позволена автовекторизация. ) У меня такие цифры (правда компилятор gcc):
Да, с /Qvec-report:2 вывод:
Выше по ветке уже был похожий пример
_>Однако даже и без автовекторизазии на твоих же цифрах видно, что разница между C++ и C# вариантом в 2 раза — это уже убойно. )))
Угу, нынешний JIT на числомолотилки не заточен, это давно известно. Чисто ради интереса: какой фреймворк и x64 или x86 вариант проверялся?
P.S. Разница в 2 раза там из-за проверок на границы массива. Для всего кроме "i=0;i<array.Length" они не убираются.
UPD Не из-за них, протупил. Для варианта с указателями на 7 сложений меньше, т.к. аналог (a[p + x]) вычисляется 1 раз. Вот этот вариант с указателями, но с доступом по индексу не отличается от safe-варианта:
UPD2 Ну да, собственно этим твои варианты под шарп и c++ и отличаются
Как только я их привёл к одному виду на автомате — время совпало с нативным результатом без автовекторизации.
Ручную векторизацию конечно можно попробовать сделать с RyuJIT + SIMD, но это уже за гранью добра и зла имхо. Нужна производительность — проще вытащить кусок в unmanaged-код и не страдать из-за "если добавить 7 лишних сложений, то шарп медленный".
_>Скорее всего дело в неверных настройках компилятора C++ — ему не позволена автовекторизация. ) У меня такие цифры (правда компилятор gcc):
Да, с /Qvec-report:2 вывод:
info C5002: loop not vectorized due to reason '1200'
// Loop contains loop-carried data dependences
Выше по ветке уже был похожий пример
Автор: PM
Дата: 05.06.15
. Компилятор c++ в vs2013 местами не блещет.Дата: 05.06.15
_>Однако даже и без автовекторизазии на твоих же цифрах видно, что разница между C++ и C# вариантом в 2 раза — это уже убойно. )))
Угу, нынешний JIT на числомолотилки не заточен, это давно известно. Чисто ради интереса: какой фреймворк и x64 или x86 вариант проверялся?
P.S. Разница в 2 раза там из-за проверок на границы массива. Для всего кроме "i=0;i<array.Length" они не убираются.
UPD Не из-за них, протупил. Для варианта с указателями на 7 сложений меньше, т.к. аналог (a[p + x]) вычисляется 1 раз. Вот этот вариант с указателями, но с доступом по индексу не отличается от safe-варианта:
unsafe static void AtoB(int[] image, int[] buf, int height)
{
int width = image.Length / height;
fixed (int* a = image, b = buf)
{
for (int y = 1; y < height - 1; y++)
{
var p = width * y;
for (int x = 1; x < width - 1; x++)
{
var idx = p + x;
if (a[idx] != 0xffffff)
{
b[idx] = (
a[idx - width] + a[idx - 1] +
a[idx - width - 1] + a[idx - width + 1] +
a[idx + width - 1] + a[idx + width] +
a[idx + 1] + a[idx + width + 1]) >> 3;
}
}
}
}
}
UPD2 Ну да, собственно этим твои варианты под шарп и c++ и отличаются
image[p-width+x] // c#
vs
s[-width+x] // c++, s == image + p
Как только я их привёл к одному виду на автомате — время совпало с нативным результатом без автовекторизации.
Ручную векторизацию конечно можно попробовать сделать с RyuJIT + SIMD, но это уже за гранью добра и зла имхо. Нужна производительность — проще вытащить кусок в unmanaged-код и не страдать из-за "если добавить 7 лишних сложений, то шарп медленный".