Повышение:: вопрос о производительности multi_array

Используйте PDO и подготовленные запросы.

($conn - объект PDO)

$stmt = $conn->prepare("INSERT INTO tbl VALUES(:id, :name)");
$stmt->bindValue(':id', $id);
$stmt->bindValue(':name', $name);
$stmt->execute();
27
задан Frank 31 December 2012 в 16:10
поделиться

12 ответов

Вы создаете выпуск или отладку?

При выполнении в режиме отладки, массив повышения мог бы быть действительно медленным, потому что их шаблонное волшебство не встраивается, правильно давая много издержек в вызовах функции. Я не уверен, как много массив реализован, хотя, таким образом, это могло бы быть полностью прочь:)

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

Попытка, переключающая порядок цикла X и Y и, видит, получаете ли Вы что-нибудь. Существует некоторая информация об устройстве хранения данных, заказывающем здесь: http://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/user.html

РЕДАКТИРОВАНИЕ: Так как Вы, кажется, используете двумерную матрицу для обработки изображений, Вы могли бы интересоваться проверкой библиотеки обработки изображений повышений gil.

Это могло бы иметь массивы с меньше служебным, который работает отлично на Вашу ситуацию.

8
ответ дан Laserallan 28 November 2019 в 04:31
поделиться

Сборка в режиме выпуска, используйте objdump и посмотрите на блок. Они могут делать совершенно другие вещи, и Вы будете в состоянии видеть, какую оптимизацию компилятор использует.

1
ответ дан bradtgmurray 28 November 2019 в 04:31
поделиться

Я думаю, что знаю то, что проблема..., возможно.

Для внедрения BOOST для имения синтаксиса как: матрица [x] [y]. это означает, что матрица [x] должна возвратить ссылку на объект, который действует как 1D массив столбец , на уровне которого ссылка точки [y] дает Вам Ваш элемент.

проблема здесь состоит в том, что Вы выполняете итерации в строка, крупнейшая порядок (который типичен в c/c ++, так как собственные массивы являются строкой главный IIRC. Компилятор должен повторно выполнить матрицу [x] для каждого y в этом случае. При итерации в столбце главного порядка при использовании матрицы повышения можно видеть лучшую производительность.

Просто теория.

РЕДАКТИРОВАНИЕ: в моей системе Linux (с некоторыми незначительными изменениями) я протестировал свою теорию и действительно показывал [приблизительно 111] повышение производительности путем переключения X и Y, но это было еще медленнее, чем собственный массив. Это могло бы быть простым выпуском компилятора, не бывшего способного оптимизировать далеко временный ссылочный тип.

1
ответ дан Evan Teran 28 November 2019 в 04:31
поделиться

Рассмотрите использование Блица ++ вместо этого. Я испытал Блиц, и его производительность на одном уровне с массивом C-стиля!

Выезд Ваш код с Блицем, добавленным ниже:

<час>
#include <windows.h>
#define _SCL_SECURE_NO_WARNINGS
#define BOOST_DISABLE_ASSERTS 
#include <boost/multi_array.hpp>
#include <blitz/array.h>

int main(int argc, char* argv[])
{
    const int X_SIZE = 200;
    const int Y_SIZE = 200;
    const int ITERATIONS = 500;
    unsigned int startTime = 0;
    unsigned int endTime = 0;

    // Create the boost array
    typedef boost::multi_array<double, 2> ImageArrayType;
    ImageArrayType boostMatrix(boost::extents[X_SIZE][Y_SIZE]);


    //------------------Measure boost----------------------------------------------
    startTime = ::GetTickCount();
    for (int i = 0; i < ITERATIONS; ++i)
    {
        for (int y = 0; y < Y_SIZE; ++y)
        {
            for (int x = 0; x < X_SIZE; ++x)
            {
                boostMatrix[x][y] = 2.345;
            }
        }
    }
    endTime = ::GetTickCount();
    printf("[Boost] Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);

    //------------------Measure blitz-----------------------------------------------
    blitz::Array<double, 2> blitzArray( X_SIZE, Y_SIZE );
    startTime = ::GetTickCount();
    for (int i = 0; i < ITERATIONS; ++i)
    {
        for (int y = 0; y < Y_SIZE; ++y)
        {
            for (int x = 0; x < X_SIZE; ++x)
            {
                blitzArray(x,y) = 2.345;
            }
        }
    }
    endTime = ::GetTickCount();
    printf("[Blitz] Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);


    //------------------Measure native-----------------------------------------------
    // Create the native array
    double *nativeMatrix = new double [X_SIZE * Y_SIZE];

    startTime = ::GetTickCount();
    for (int i = 0; i < ITERATIONS; ++i)
    {
        for (int y = 0; y < Y_SIZE; ++y)
        {
            for (int x = 0; x < X_SIZE; ++x)
            {
                nativeMatrix[x + (y * X_SIZE)] = 2.345;
            }
        }
    }
    endTime = ::GetTickCount();
    printf("[Native]Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);



    return 0;
}
<час>

Вот результат в отладке и выпуске.

ОТЛАДКА:

Boost  2.093 secs 
Blitz  0.375 secs 
Native 0.078 secs

ВЫПУСК:

Boost  0.266 secs
Blitz  0.016 secs
Native 0.015 secs

я использовал компилятор SP1 MSVC 2008 для этого.

мы можем теперь сказать до свидания массиву C-stlye? =p

4
ответ дан Paul Hiemstra 28 November 2019 в 04:31
поделиться

Другая вещь попробовать состоит в том, чтобы использовать итераторы вместо прямого индекса для массива повышения.

2
ответ дан bradtgmurray 28 November 2019 в 04:31
поделиться

Я задаюсь вопросом две вещи:

1) граничная проверка: определите макрос препроцессора BOOST_DISABLE_ASSERTS до включения multi_array.hpp в Вашем приложении. Это выключает связанную проверку. не уверенный, если это это, отключает, когда NDEBUG.

2) базисный индекс: MultiArray может индексировать массивы от оснований, отличающихся от 0. Это означает, что multi_array хранит основание системы счисления (в каждом размере) и использует более сложную формулу для получения точного местоположения в памяти, я задаюсь вопросом, является ли это все об этом.

Иначе я не понимаю, почему мультимассив должен быть медленнее, чем C-массивы.

4
ответ дан 28 November 2019 в 04:31
поделиться

Ваш тест испорчен.

  • В Отладочная сборка, повышение:: MultiArray испытывает недостаток в оптимизационном проходе, в котором он очень нуждается. (Намного больше, чем собственный массив был бы)
  • В СБОРКЕ КОНЕЧНЫХ ВЕРСИЙ, Ваш компилятор будет искать код, который может быть удален напрямую и , большая часть Вашего кода находится в той категории .

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

Делают это небольшое изменение Вашего испытательного стенда , и Вы будете видеть больше реалистических результатов: Измените оба происшествия" = 2.345 "с" *= 2.345 "и скомпилируйте снова с оптимизацией. Это будет препятствовать тому, чтобы Ваш компилятор обнаружил, что внешний цикл каждого теста избыточен.

я сделал это и получил сравнение скорости ближе с 2:1.

11
ответ дан Drew Dormann 28 November 2019 в 04:31
поделиться

На моей машине, используя

g++ -O3 -march=native -mtune=native --fast-math -DNDEBUG test.cpp -o test && ./test

, я получаю

[Boost] Elapsed time:  0.020 seconds
[Native]Elapsed time:  0.020 seconds

Однако, меняя const int ITERATIONS на 5000, я получаю

[Boost] Elapsed time:  0.240 seconds
[Native]Elapsed time:  0.180 seconds

и затем ITERATIONS вернуться к 500, но X_SIZE и Y_SIZE установить на 400 Я получаю гораздо более существенную разницу

[Boost] Elapsed time:  0.460 seconds
[Native]Elapsed time:  0.070 seconds

, наконец, инвертируя внутренний цикл для случая [Boost], чтобы он выглядел как

    for (int x = 0; x < X_SIZE; ++x)
    {
        for (int y = 0; y < Y_SIZE; ++y)
        {

и сохраняя ITERATIONS, X_SIZE и Y_SIZE в 500, 400 и 400, я получаю

[Boost] Elapsed time:  0.060 seconds
[Native]Elapsed time:  0.080 seconds

Если я инвертирую Внутренний цикл также для случая [Native] (так что в неправильном порядке для этого случая) я получаю, что неудивительно,

[Boost] Elapsed time:  0.070 seconds
[Native]Elapsed time:  0.450 seconds

Я использую gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 в Ubuntu 10.10

] Итак, в заключение:

  • При правильная оптимизация boost :: multi_array выполняет свою работу, как и ожидалось
  • Порядок доступа к вашим данным делает материя
33
ответ дан rodrigob 28 November 2019 в 04:31
поделиться

Я ожидал бы, что мультимассив будет так же эффективен. Но я получаю подобные результаты на Mac PPC с помощью gcc. Я также попробовал multiarrayref, так, чтобы обе версии использовали то же устройство хранения данных без различия. Это хорошо для знания, так как я использую мультимассив в части моего кода, и просто предположил, что это было подобно кодированию руки.

2
ответ дан KeithB 28 November 2019 в 04:31
поделиться

Аналогичный вопрос был задан и дан ответ здесь:

http: // www.codeguru.com/forum/archive/index.php/t-300014.html

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

Компиляторы также могут различаться по тому, насколько хорошо они будут оптимизировать по сравнению с тем, насколько они будут консервативными (например, с шаблонным кодом или другими сложностями).

1
ответ дан 28 November 2019 в 04:31
поделиться

Я модифицировал приведенный выше код в визуальной студии 2008 v9.0.21022 и применил контейнерные подпрограммы из Numerical Recipe для C и C++

http://www.nrbook.com/nr3/, используя их лицензионные подпрограммы dmatrix и MatDoub соответственно

dmatrix использует устаревший синтаксический оператор malloc и не рекомендуется.... MatDoub использует команду New

Скорость в секундах в Release версии:

Boost: 0.437

Native: 0.032

Numerical Recipes C: 0.031

Numerical Recipes C: 0.031

So from the above blitz looks like the best free alternative.

0
ответ дан 28 November 2019 в 04:31
поделиться

Я тестировал на Snow Leopard Mac OS, используя gcc 4.2.1

Debug:
[Boost] Elapsed time:  2.268 seconds
[Native]Elapsed time:  0.076 seconds

Release:
[Boost] Elapsed time:  0.065 seconds
[Native]Elapsed time:  0.020 seconds

Вот код (измененный так, чтобы его можно было компилировать на Unix):

#define BOOST_DISABLE_ASSERTS
#include <boost/multi_array.hpp>
#include <ctime>

int main(int argc, char* argv[])
{
    const int X_SIZE = 200;
    const int Y_SIZE = 200;
    const int ITERATIONS = 500;
    unsigned int startTime = 0;
    unsigned int endTime = 0;

    // Create the boost array
    typedef boost::multi_array<double, 2> ImageArrayType;
    ImageArrayType boostMatrix(boost::extents[X_SIZE][Y_SIZE]);

    // Create the native array
    double *nativeMatrix = new double [X_SIZE * Y_SIZE];

    //------------------Measure boost----------------------------------------------
    startTime = clock();
    for (int i = 0; i < ITERATIONS; ++i)
    {
        for (int y = 0; y < Y_SIZE; ++y)
        {
            for (int x = 0; x < X_SIZE; ++x)
            {
                boostMatrix[x][y] = 2.345;
            }
        }
    }
    endTime = clock();
    printf("[Boost] Elapsed time: %6.3f seconds\n", (endTime - startTime) / (double)CLOCKS_PER_SEC);

    //------------------Measure native-----------------------------------------------
    startTime = clock();
    for (int i = 0; i < ITERATIONS; ++i)
    {
        for (int y = 0; y < Y_SIZE; ++y)
        {
            for (int x = 0; x < X_SIZE; ++x)
            {
                nativeMatrix[x + (y * X_SIZE)] = 2.345;
            }
        }
    }
    endTime = clock();
    printf("[Native]Elapsed time: %6.3f seconds\n", (endTime - startTime) / (double)CLOCKS_PER_SEC);

    return 0;
}
1
ответ дан 28 November 2019 в 04:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: