سؤال

أنا أحاول أن مقارنة أداء دفعة::multi_array الأصلية تخصيصها المصفوفات مع البرنامج الاختبار التالي:

#include <windows.h>
#define _SCL_SECURE_NO_WARNINGS
#define BOOST_DISABLE_ASSERTS 
#include <boost/multi_array.hpp>

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 = ::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 native-----------------------------------------------
    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] Elapsed time: 12.500 seconds
[Native]Elapsed time:  0.062 seconds

لا أصدق multi_arrays هي أبطأ بكثير.يمكن لأي شخص بقعة ما أقوم به خطأ ؟

أفترض التخزين المؤقت ليست قضية منذ أفعل يكتب إلى الذاكرة.

تحرير:كان هذا التصحيح بناء.في Laserallan ما توحي فعلت بناء الإصدار:

[Boost] Elapsed time:  0.266 seconds
[Native]Elapsed time:  0.016 seconds

أقرب بكثير.ولكن 16 إلى 1 لا يزال يبدو مرتفعا بالنسبة لي.

حسنا لا توجد إجابة قاطعة, ولكن انا ذاهب الى المضي قدما و ترك بلدي رمز حقيقي مع الأم المصفوفات الآن.

قبول Laserallan الجواب لأنه كان أكبر عيب في الاختبار.

شكرا للجميع.

هل كانت مفيدة؟

المحلول

هل بناء الإفراج عنهم أو التصحيح؟

إذا تشغيل في وضع التصحيح، قد يكون دفعة مجموعة بطيئة حقا لأنه لم يتم inlined السحر قالب عطائهم الكثير من النفقات العامة في المكالمات تعمل بشكل صحيح. أنا لست متأكدا من مجموعة متعددة يتم تنفيذه على الرغم من ذلك وهذا قد يكون تماما قبالة:)

وربما يكون هناك بعض الاختلاف من أجل التخزين، وكذلك لذلك قد تكون لديها صورة العمود المخزنة بواسطة عمود وكتابته من صف. وهذا من شأنه إعطاء السلوك مخبأ الفقراء وقد تبطئ الأشياء.

وحاول تبديل ترتيب حلقة X و Y ونرى ما اذا كان يمكنك الحصول على أي شيء. هناك بعض المعلومات حول ترتيب تخزين هنا: http://www.boost.org/doc/libs /1_37_0/libs/multi_array/doc/user.html

وتحرير: منذ يبدو أنك تستخدم مجموعة الأبعاد لمعالجة الصور التي قد تكون مهتمة في التحقق من يعزز مكتبة معالجة الصور <لأ href = "http://www.boost.org/doc/libs/1_37_0/libs/gil/doc /index.html "يختلط =" noreferrer "> جيل .

وقد يكون صفائف مع أقل من النفقات العامة الذي يعمل تماما مع الموقف الخاص بك.

نصائح أخرى

على الجهاز الخاص بي باستخدام

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 على أوبونتو 10.10

حتى في الختام:

  • مع التحسين المناسبة دفعة::multi_array لا وظيفة لها كما هو متوقع
  • الأمر الذي يمكنك الوصول إلى البيانات الخاصة بك لا يهم

الاختبار هو معيب.

  • في بناء تصحيح وزيادة::MultiArray يفتقر إلى التحسين تمر أنها تحتاج بشدة.(أكثر من الأم أن مجموعة)
  • في بيان بناء, المترجم الخاص بك سوف تبدو التعليمات البرمجية التي يمكن إزالتها على الفور ، معظم التعليمات البرمجية الخاصة بك في هذه الفئة.

ما أنت من المحتمل رؤية هو نتيجة الخاص بك تحسين مترجم رؤية أن معظم أو كل من "الأم مجموعة" الحلقات يمكن إزالتها.نفس صحيحا من الناحية النظرية من دفعة الخاص بك::MultiArray الحلقات ، ولكن MultiArray وربما معقدة بما فيه الكفاية لهزيمة محسن.

جعل هذا التغيير صغيرة إلى اختبارات وسترى المزيد من صحيح إلى الحياة النتائج:تغيير كل من حدوث "= 2.345 "مع "*= 2.345 "وتجميع مرة أخرى مع تحسينات.هذا سوف منع المترجم من اكتشاف أن الحلقة الخارجية من كل اختبار هو زائد عن الحاجة.

أنا فعلت هذا و حصلت على مقارنة سرعة أقرب إلى 2:1.

وأنا أتساءل أمرين:

1) حدود الاختيار: تعريف الماكرو BOOST_DISABLE_ASSERTS المعالج قبل بما في ذلك multi_array.hpp في التطبيق الخاص بك. هذا إيقاف فحص منضم. لست متأكدا إذا كان هذا هذا هو تعطيل عندما NDEBUG هو.

2) مؤشر قاعدة:  MultiArray يمكن صفائف مؤشر من أسس مختلفة من 0. وهذا يعني أن مخازن multi_array عدد قاعدة (في كل البعد) ويستخدم صيغة أكثر تعقيدا للحصول على المكان المحدد في الذاكرة، وأنا أتساءل عما اذا كان هو كل شيء عن ذلك.

وإلا أنا لا أفهم لماذا multiarray ينبغي أن يكون أبطأ من C-المصفوفات.

والنظر في استخدام الغارة ++ بدلا من ذلك. حاولت من الغارة، وأدائها على قدم المساواة مع مجموعة على غرار 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;
}

وهنا النتيجة في التصحيح والافراج عنهم.

وDEBUG:

Boost  2.093 secs 
Blitz  0.375 secs 
Native 0.078 secs

وRELEASE:

Boost  0.266 secs
Blitz  0.016 secs
Native 0.015 secs

واعتدت MSVC 2008 مترجم SP1 لذلك.

هل يمكن القول الآن وداعا لمجموعة C-ستليي؟ = p

كنت أبحث في هذه المسألة لأنه كان لدي نفس السؤال.لدي أفكار لإعطاء صورة أكثر دقة الاختبار.

  1. كما rodrigob أشار إلى أن هناك عيوب في حلقة هذا أن أي نتائج في التعليمات البرمجية التي قمت أصلا المرفقة تعطي بيانات مضللة
  2. أيضا ، هناك بدلا صغيرة الحجم المصفوفات التي يتم إعدادها باستخدام الثوابت.المترجم قد يكون الأمثل من الحلقات ، بينما في الواقع فإن المترجم لا يعرف حجم المصفوفات.أحجام المصفوفات و عدد التكرارات يجب أن يكون وقت المدخلات فقط في حالة.

على ماك, التعليمة البرمجية التالية إلى تكوين تعطي إجابات أكثر وضوحا.هناك 4 اختبارات هنا.

#define BOOST_DISABLE_ASSERTS
#include "boost/multi_array.hpp"
#include <sys/time.h>
#include <stdint.h>
#include<string>

uint64_t GetTimeMs64()
{
  struct timeval tv;

  gettimeofday( &tv, NULL );

  uint64_t ret = tv.tv_usec;
  /* Convert from micro seconds (10^-6) to milliseconds (10^-3) */
  ret /= 1000;

  /* Adds the seconds (10^0) after converting them to milliseconds (10^-3) */
  ret += ( tv.tv_sec * 1000 );

  return ret;

}


void function1( const int X_SIZE, const int Y_SIZE, const int ITERATIONS )
{

  double nativeMatrix1add[X_SIZE*Y_SIZE];

  for( int x = 0 ; x < X_SIZE ; ++x )
  {
    for( int y = 0 ; y < Y_SIZE ; ++y )
    {
      nativeMatrix1add[y + ( x * Y_SIZE )] = rand();
    }
  }

  // Create the native array
  double* __restrict const nativeMatrix1p = new double[X_SIZE * Y_SIZE];
  uint64_t startTime = GetTimeMs64();
  for( int i = 0 ; i < ITERATIONS ; ++i )
  {
    for( int xy = 0 ; xy < X_SIZE*Y_SIZE ; ++xy )
    {
      nativeMatrix1p[xy] += nativeMatrix1add[xy];
    }
  }
  uint64_t endTime = GetTimeMs64();
  printf( "[Native Pointer]    Elapsed time: %6.3f seconds\n", ( endTime - startTime ) / 1000.0 );

}

void function2( const int X_SIZE, const int Y_SIZE, const int ITERATIONS )
{

  double nativeMatrix1add[X_SIZE*Y_SIZE];

  for( int x = 0 ; x < X_SIZE ; ++x )
  {
    for( int y = 0 ; y < Y_SIZE ; ++y )
    {
      nativeMatrix1add[y + ( x * Y_SIZE )] = rand();
    }
  }

  // Create the native array
  double* __restrict const nativeMatrix1 = new double[X_SIZE * Y_SIZE];
  uint64_t startTime = GetTimeMs64();
  for( int i = 0 ; i < ITERATIONS ; ++i )
  {
    for( int x = 0 ; x < X_SIZE ; ++x )
    {
      for( int y = 0 ; y < Y_SIZE ; ++y )
      {
        nativeMatrix1[y + ( x * Y_SIZE )] += nativeMatrix1add[y + ( x * Y_SIZE )];
      }
    }
  }
  uint64_t endTime = GetTimeMs64();
  printf( "[Native 1D Array]   Elapsed time: %6.3f seconds\n", ( endTime - startTime ) / 1000.0 );

}


void function3( const int X_SIZE, const int Y_SIZE, const int ITERATIONS )
{

  double nativeMatrix2add[X_SIZE][Y_SIZE];

  for( int x = 0 ; x < X_SIZE ; ++x )
  {
    for( int y = 0 ; y < Y_SIZE ; ++y )
    {
      nativeMatrix2add[x][y] = rand();
    }
  }

  // Create the native array
  double nativeMatrix2[X_SIZE][Y_SIZE];
  uint64_t startTime = GetTimeMs64();
  for( int i = 0 ; i < ITERATIONS ; ++i )
  {
    for( int x = 0 ; x < X_SIZE ; ++x )
    {
      for( int y = 0 ; y < Y_SIZE ; ++y )
      {
        nativeMatrix2[x][y] += nativeMatrix2add[x][y];
      }
    }
  }
  uint64_t endTime = GetTimeMs64();
  printf( "[Native 2D Array]   Elapsed time: %6.3f seconds\n", ( endTime - startTime ) / 1000.0 );

}



void function4( const int X_SIZE, const int Y_SIZE, const int ITERATIONS )
{

  boost::multi_array<double, 2> boostMatrix2add( boost::extents[X_SIZE][Y_SIZE] );

  for( int x = 0 ; x < X_SIZE ; ++x )
  {
    for( int y = 0 ; y < Y_SIZE ; ++y )
    {
      boostMatrix2add[x][y] = rand();
    }
  }

  // Create the native array
  boost::multi_array<double, 2> boostMatrix( boost::extents[X_SIZE][Y_SIZE] );
  uint64_t startTime = GetTimeMs64();
  for( int i = 0 ; i < ITERATIONS ; ++i )
  {
    for( int x = 0 ; x < X_SIZE ; ++x )
    {
      for( int y = 0 ; y < Y_SIZE ; ++y )
      {
        boostMatrix[x][y] += boostMatrix2add[x][y];
      }
    }
  }
  uint64_t endTime = GetTimeMs64();
  printf( "[Boost Array]       Elapsed time: %6.3f seconds\n", ( endTime - startTime ) / 1000.0 );

}

int main( int argc, char* argv[] )
{

  srand( time( NULL ) );

  const int X_SIZE = std::stoi( argv[1] );
  const int Y_SIZE = std::stoi( argv[2] );
  const int ITERATIONS = std::stoi( argv[3] );

  function1( X_SIZE, Y_SIZE, ITERATIONS );
  function2( X_SIZE, Y_SIZE, ITERATIONS );
  function3( X_SIZE, Y_SIZE, ITERATIONS );
  function4( X_SIZE, Y_SIZE, ITERATIONS );

  return 0;
}
  1. واحد مع واحد فقط الصفيف الأبعاد باستخدام [] مع عدد صحيح الرياضيات و حلقة مزدوجة

  2. واحد مع نفس واحدة الأبعاد المصفوفة باستخدام مؤشر تزايد

  3. متعدد الأبعاد ج مجموعة

  4. دفعة multi_array

حتى تشغيلها من سطر الأوامر تشغيل

./test_array xsize ysize iterations"

و يمكنك الحصول على فكرة جيدة عن كيفية هذه الأساليب سوف تؤدي.هنا هو ما حصلت مع برنامج التحويل البرمجي التالية الأعلام:

g++4.9.2 -O3 -march=native -funroll-loops -mno-avx --fast-math -DNDEBUG  -c -std=c++11


./test_array 51200 1 20000
[Native 1-Loop ]    Elapsed time:  0.537 seconds
[Native 1D Array]   Elapsed time:  2.045 seconds
[Native 2D Array]   Elapsed time:  2.749 seconds
[Boost Array]       Elapsed time:  1.167 seconds

./test_array 25600 2 20000
[Native 1-Loop ]    Elapsed time:  0.531 seconds
[Native 1D Array]   Elapsed time:  1.241 seconds
[Native 2D Array]   Elapsed time:  1.631 seconds
[Boost Array]       Elapsed time:  0.954 seconds

./test_array 12800 4 20000
[Native 1-Loop ]    Elapsed time:  0.536 seconds
[Native 1D Array]   Elapsed time:  1.214 seconds
[Native 2D Array]   Elapsed time:  1.223 seconds
[Boost Array]       Elapsed time:  0.798 seconds

./test_array 6400 8 20000
[Native 1-Loop ]    Elapsed time:  0.540 seconds
[Native 1D Array]   Elapsed time:  0.845 seconds
[Native 2D Array]   Elapsed time:  0.878 seconds
[Boost Array]       Elapsed time:  0.803 seconds

./test_array 3200 16 20000
[Native 1-Loop ]    Elapsed time:  0.537 seconds
[Native 1D Array]   Elapsed time:  0.661 seconds
[Native 2D Array]   Elapsed time:  0.673 seconds
[Boost Array]       Elapsed time:  0.708 seconds

./test_array 1600 32 20000
[Native 1-Loop ]    Elapsed time:  0.532 seconds
[Native 1D Array]   Elapsed time:  0.592 seconds
[Native 2D Array]   Elapsed time:  0.596 seconds
[Boost Array]       Elapsed time:  0.764 seconds

./test_array 800 64 20000
[Native 1-Loop ]    Elapsed time:  0.546 seconds
[Native 1D Array]   Elapsed time:  0.594 seconds
[Native 2D Array]   Elapsed time:  0.606 seconds
[Boost Array]       Elapsed time:  0.764 seconds

./test_array 400 128 20000
[Native 1-Loop ]    Elapsed time:  0.536 seconds
[Native 1D Array]   Elapsed time:  0.560 seconds
[Native 2D Array]   Elapsed time:  0.564 seconds
[Boost Array]       Elapsed time:  0.746 seconds

لذا أعتقد أنه من الأسلم أن نقول أن زيادة multi_array ينفذ جيدة.لا شيء يدق حلقة واحدة التقييم ، ولكن اعتمادا على البعد من مجموعة ، دفعة::multi_array قد فاز القياسية ج-مجموعة مع حلقة مزدوجة.

وشيء آخر هو محاولة لاستخدام التكرارات بدلا من مؤشر على التوالي لدعم مجموعة.

وكان يتوقع multiarray أن تكون مجرد فعالة كما كنت. ولكن أنا الحصول على نتائج مماثلة على PPC ماك باستخدام دول مجلس التعاون الخليجي. كما أنني حاولت multiarrayref، بحيث كلا الإصدارين يستخدمون نفس التخزين لا فرق. هذا أمر جيد أن نعرف، منذ أن استخدام multiarray في بعض قانون بلدي، ومجرد افتراض أنها مماثلة لتسليم الترميز.

أعتقد أنني أعرف ما هي المشكلة...ربما.

من أجل تعزيز التنفيذ أن يكون بناء الجملة مثل:مصفوفة[x][y].وهذا يعني أن المصفوفة[x] وقد لإرجاع مرجع إلى كائن الذي يتصرف مثل 1D مجموعة العمود, في هذه النقطة المرجعية[y] يعطيك العنصر الخاص بك.

المشكلة هنا هي أن تقوم بالتكرار في الصف الرئيسية النظام (والتي هي الحال في c/c++ منذ الأصلية المصفوفات هي صف الرئيسية IIRC.المترجم له إلى إعادة تنفيذ مصفوفة[x] لكل y في هذه الحالة.إذا كنت يتحرك في العمود الرئيسية عند استخدامك دفعة مصفوفة ، قد نرى أداء أفضل.

مجرد نظرية.

تحرير:على نظام لينكس (مع بعض التغييرات الطفيفة) اختبرت نظريتي و لم تظهر بعض تحسين الأداء من خلال التبديل x و y, ولكن كان لا يزال أبطأ من مواليد الصفيف.قد تكون هذه قضية بسيطة من المترجم لا يجري قادرة على تحسين بعيدا المؤقتة نوع مرجع.

وبناء في وضع الإصدار، استخدم objdump، وإلقاء نظرة على التجمع. ويمكن القيام بأشياء مختلفة تماما، وعليك أن تكون قادرا على رؤية التي أمثل المترجم يستخدم.

وكان طرح سؤال مماثل وأجاب هنا:

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

والجواب القصير هو أنه أسهل للمترجم لتحسين المصفوفات بسيطة، وليس من السهل لتحسين إصدار دفعة. وبالتالي، مترجم معين قد لا تعطي النسخة تفعيل جميع المزايا الأمثل نفسها.

ويمكن أيضا أن تختلف

والمجمعين في مدى حسن وتحسين مقابل كيفية المحافظة أنها ستكون (على سبيل المثال مع رمز قالب أو مضاعفات أخرى).

واختبرت على سنو ليوبارد ماك 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

وهنا، هو رمز (تعديل بحيث يمكن جمعها على يونيكس):

#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;
}

وإذا نظرنا إلى الجمعية التي تم إنشاؤها بواسطة ز ++ 4.8.2 مع -O3 -DBOOST_DISABLE_ASSERTS وباستخدام كل من operator() والطرق [][] للوصول إلى العناصر، فإنه من الواضح أن عملية اضافية فقط مقارنة مع صفائف الأم واليدوي مؤشر حساب هو إضافة للقاعدة. لم أكن قياس تكلفة هذا بالرغم من ذلك.

وI تعديل التعليمات البرمجية أعلاه في Visual Studio 2008 v9.0.21022 وتطبيق إجراءات حاوية من إجراءات وصفة العددية لC و C ++

http://www.nrbook.com/nr3/ استخدام مواردها المرخص الروتينية dmatrix و MatDoub على التوالي

وdmatrix يستخدم من جملة تاريخ المشغل malloc ولا ينصح ... يستخدم MatDoub الأمر جديد

وسرعة في ثوان هي في الإصدار الإصدار:

ودفعة: 0.437

وأصلي: 0.032

والعددية وصفات C: 0،031

وصفات العددي C ++: 0،031

وهكذا من بدء الهجوم المذكور أعلاه يبدو أفضل بديل مجانا.

ولقد قمت بتجميع رمز (مع تعديلات طفيفة) تحت VC ++ 2010 مع تحسين تشغيل ( "تكبير سرعة" جنبا إلى جنب مع رمز مصدر "أي مناسبة" وظائف و "تفضيل كود السريع") وحصلت الأوقات 0.015 / 0.391. لقد ولدت قائمة التجمع، وعلى الرغم من أنني مستجد التجمع الرهيب، وهناك خط واحد داخل الحلقة قياس دفعة التي لا تبدو جيدة بالنسبة لي:

call    ??A?$multi_array_ref@N$01@boost@@QAE?AV?$sub_array@N$00@multi_array@detail@1@H@Z ; boost::multi_array_ref<double,2>::operator[]

واحدة من [] شركات لم تحصل على inlined! الإجراء يسمى يجعل مكالمة أخرى، وهذه المرة إلى multi_array::value_accessor_n<...>::access<...>():

call    ??$access@V?$sub_array@N$00@multi_array@detail@boost@@PAN@?$value_accessor_n@N$01@multi_array@detail@boost@@IBE?AV?$sub_array@N$00@123@U?$type@V?$sub_array@N$00@multi_array@detail@boost@@@3@HPANPBIPBH3@Z ; boost::detail::multi_array::value_accessor_n<double,2>::access<boost::detail::multi_array::sub_array<double,1>,double *>

وإجمالا، فإن الإجراءات هما الكثير جدا من التعليمات البرمجية لمجرد الوصول إلى عنصر واحد في مجموعة. انطباعي العام هو أن المكتبة هي معقدة جدا ورفيع المستوى البصرية ستوديو غير قادر على تحسين بقدر ما نود (ملصقات باستخدام دول مجلس التعاون الخليجي على ما يبدو قد حصلت على نتائج أفضل).

وIMHO، مترجم جيد حقا يجب أن inlined والأمثل الإجراءين - كلاهما قصيرة جدا ومستقيم إلى الأمام، لا تحتوي على أي حلقات الخ وهناك الكثير من الوقت قد تضيع ببساطة على تمرير الوسائط ونتائجها.

ووالإجابة عليها من قبل rodrigob، وتفعيل التحسين المناسبة (الافتراضي دول مجلس التعاون الخليجي هو -O0) هو المفتاح للحصول على الأداء الجيد. وبالإضافة إلى ذلك، اختبرت أيضا مع الحريق DynamicMatrix ، مما أدى إلى تحقيق إضافي تحسين أداء عامل 2 مع الدقيقة أعلام الأمثل نفسها. https://bitbucket.org/account/user/blaze-lib/projects/ الحريق

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top