বর্ণালী আদর্শ শুটআউটে (জিসিসি, ইন্টেল এবং অন্যান্য সংকলক ব্যবহার করে) সি কি ফোর্টরানের চেয়ে ধীর?


13

এখানে উপসংহার:

ফোর্টরান সংকলকরা আরও কতটা ভাল?

যে গফর্ট্রান এবং জিসিসি সহজ কোডের জন্য তত দ্রুত। তাই আমি আরও জটিল কিছু চেষ্টা করতে চেয়েছিলাম। বর্ণালী আদর্শ শুটআউটের উদাহরণ নিলাম। আমি প্রথমে 2 ডি ম্যাট্রিক্স এ (:, :) :) কে প্রাক্ক্যালকুলেট করি এবং তারপরে আদর্শটি গণনা করি। (আমার মনে হয় শ্যুটআউটে এই সমাধানটির অনুমতি নেই)) আমি ফোর্টরান এবং সি সংস্করণটি প্রয়োগ করেছি। কোডটি এখানে:

https://github.com/certik/spectral_norm

দ্রুততম গফর্ট্রান সংস্করণগুলি বর্ণালি_ নরম 2.f90 এবং বর্ণাল_নর্ম 6.f90 (একটি ফোর্টরানের অন্তর্নির্মিত ম্যাটমুল এবং ডট_প্রডাক্ট ব্যবহার করে, অন্যটি কোডটিতে এই দুটি ফাংশন প্রয়োগ করে - গতির কোনও পার্থক্য ছাড়াই)। আমি যে দ্রুতগতিতে সি / সি ++ কোড লিখতে পেরেছি তা হ'ল বর্ণালী_নর্ম 7 সিপিপি। আমার ল্যাপটপে 457d9d9 গিট সংস্করণ অনুসারে সময়গুলি হ'ল:

$ time ./spectral_norm6 5500
1.274224153

real    0m2.675s
user    0m2.520s
sys 0m0.132s


$ time ./spectral_norm7 5500
1.274224153

real    0m2.871s
user    0m2.724s
sys 0m0.124s

তাই গফর্ট্রানের সংস্করণটি কিছুটা দ্রুত। কেন এমন? আপনি যদি দ্রুত সি প্রয়োগের সাথে একটি টান অনুরোধ প্রেরণ করেন (বা কেবল একটি কোড পেস্ট করুন), আমি সংগ্রহস্থলটি আপডেট করব।

ফোর্টরানে আমি প্রায় 2D অ্যারে পাস করি, যখন সিআইতে 1D অ্যারে ব্যবহার করি। একটি 2D অ্যারে বা আপনি যেভাবে ফিট দেখতে চান তা অন্য কোনও উপায়ে নির্দ্বিধায় ব্যবহার করুন।

সংকলক হিসাবে, আসুন জিসিসি বনাম গফর্ট্রান, আইসিসি বনাম আইফোর্ট এবং আরও অনেক কিছু তুলনা করি। (শুটআউট পৃষ্ঠার বিপরীতে, যা আইফোর্ট বনাম জিসিসি তুলনা করে))

আপডেট : আমার সি সংস্করণে ম্যাটমুল 3 () উন্নত করে 179dae2 সংস্করণটি ব্যবহার করে তারা এখন তত দ্রুত:

$ time ./spectral_norm6 5500
1.274224153

real    0m2.669s
user    0m2.500s
sys 0m0.144s

$ time ./spectral_norm7 5500
1.274224153

real    0m2.665s
user    0m2.472s
sys 0m0.168s

নীচে পেড্রোর ভেক্টরাইজড সংস্করণটি দ্রুত:

$ time ./spectral_norm8 5500
1.274224153

real    0m2.523s
user    0m2.336s
sys 0m0.156s

অবশেষে, ইনটেল সংকলকগুলির জন্য নীচের ল্যাক্সি রিপোর্ট হিসাবে, সেখানে খুব বড় পার্থক্য বলে মনে হচ্ছে না এবং এমনকি সর্বাধিক সহজ ফোর্টরান কোড (বর্ণালী_নরম 1) দ্রুততম মধ্যে রয়েছে।


5
আমি এখনই কোনও সংকলকের নিকটে নেই, তবে আপনার অ্যারেগুলিতে সীমাবদ্ধ কীওয়ার্ড যুক্ত করার বিষয়টি বিবেচনা করুন। পয়েন্টার অ্যালিজিং সাধারণত অ্যারেগুলিতে ফোর্টরান এবং সি ফাংশন কলগুলির মধ্যে পার্থক্য। এছাড়াও, ফোর্টরান কলাম-প্রধান ক্রমে মেমরি সঞ্চয় করে এবং সারি-প্রধানতে সি।
ময়নার

1
-1 এই প্রশ্নের মূল অংশ বাস্তবায়ন সম্পর্কে কথা বলে তবে শিরোনামটি জিজ্ঞাসা করে কোন ভাষাটি দ্রুত? একটি ভাষার গতির একটি বৈশিষ্ট্য কীভাবে থাকতে পারে? আপনার প্রশ্নের শিরোনামটি সম্পাদনা করা উচিত যাতে এটি প্রশ্নের শরীরকে প্রতিবিম্বিত করে।
মিলঙ্কুরিক

@ IRO-bot, আমি এটি ঠিক করেছি fixed আপনার কাছে এটি ঠিক আছে কিনা তা আমাকে জানাবেন।
ওঁদেজ এর্তিক

1
আসলে "ফোর্টরান সংকলকরা আসলে কতটা ভাল" এই সিদ্ধান্তে সিদ্ধান্ত নিয়েছেন? এই থ্রেডে বেশ সঠিক নয়। আমি জিসিসি, পিজিআই, সিআরআই এবং ইন্টেল সংকলক এবং 3 সংকলক সহ ফোরট্রান সি (বি / ডাব্লু- 5-40%) এর চেয়ে দ্রুত গতিতে একটি ক্রিতে বেঞ্চমার্কটি চেষ্টা করেছি। ক্রে সংকলকগুলি দ্রুত ফরট্রান / সি কোড তৈরি করেছিল তবে ফোর্টরান কোডটি 40% দ্রুত ছিল। আমি সময় পেলে বিস্তারিত ফলাফল পোস্ট করব। ক্রে মেশিনে অ্যাক্সেস সহ বিটিডব্লু যে কেউ বেঞ্চমার্কটি যাচাই করতে পারে। এটি একটি ভাল প্ল্যাটফর্ম কারণ 4-5 সংকলক উপলব্ধ এবং প্রাসঙ্গিক পতাকাগুলি ftn / cc র‍্যাপার দ্বারা স্বয়ংক্রিয়ভাবে নিযুক্ত থাকে।
stally

এছাড়াও অজিটারন সিস্টেমে pgf95 / pgcc (১১.১০) দিয়ে পরীক্ষা করা হয়েছে: # 1 এবং # 2 দ্রুততম (ort 20% দ্বারা আইফোর্টের চেয়ে দ্রুত), তারপরে # 6, # 8, # 7 (সেই ক্রমে)। pgf95 আপনার সমস্ত ফরট্রান কোডগুলির জন্য ifort চেয়ে দ্রুত ছিল, এবং আইসিপিসি সমস্ত সি এর জন্য পিজিপিপি-র চেয়ে দ্রুত ছিল - আমার উল্লেখ করা উচিত যে আমার স্টাফের জন্য, আমি সাধারণত একই এএমডি সিস্টেমে দ্রুত আইফোর্টটি খুঁজে পাই।
ল্যাক্স্সি

উত্তর:


12

সবার আগে, এই প্রশ্ন / চ্যালেঞ্জ পোস্ট করার জন্য ধন্যবাদ! অস্বীকৃতি হিসাবে, আমি কিছু ফোর্টরান অভিজ্ঞতা সহ একটি নেটিভ সি প্রোগ্রামার, এবং সিতে বাড়ির বেশিরভাগ বোধ করি, সুতরাং আমি কেবল সি সংস্করণের উন্নতিতে মনোনিবেশ করব। আমি সমস্ত ফোর্টরান হ্যাকগুলিকে তাদের যাওয়ার জন্য আমন্ত্রণ জানাই!

কেবল নতুনদের এটি সম্পর্কে কী তা মনে করিয়ে দেওয়ার জন্য: এই থ্রেডের প্রাথমিক ভিত্তিটি ছিল যে জিসিসি / ফোর্ট্রান এবং আইসিসি / আইফোর্টের যথাক্রমে একই ব্যাক-এন্ডস থাকা উচিত, নির্বিশেষে একই (শব্দার্থবিজ্ঞানযুক্ত) প্রোগ্রামের জন্য সমমানের কোড তৈরি করা উচিত এটি সি বা ফোর্টরানে রয়েছে। ফলাফলের মানটি কেবলমাত্র সংশ্লিষ্ট বাস্তবায়নের মানের উপর নির্ভর করে।

আমি কিছুটা কোড দিয়ে এবং আমার কম্পিউটারে (থিংকপ্যাড 201x, ইন্টেল কোর আই 5 এম 560, 2.67 গিগাহার্টজ) gcc4.6.1 এবং নিম্নলিখিত সংকলক পতাকা ব্যবহার করে খেললাম :

GCCFLAGS= -O3 -g -Wall -msse2 -march=native -funroll-loops -ffast-math -fomit-frame-pointer -fstrict-aliasing

আমি আরও এগিয়ে গিয়েছিলাম এবং সি ++ কোডের একটি সিমডি-ভেক্টরাইজড সি-ভাষা সংস্করণ লিখেছিলাম spectral_norm_vec.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

/* Define the generic vector type macro. */  
#define vector(elcount, type)  __attribute__((vector_size((elcount)*sizeof(type)))) type

double Ac(int i, int j)
{
    return 1.0 / ((i+j) * (i+j+1)/2 + i+1);
}

double dot_product2(int n, double u[], double v[])
{
    double w;
    int i;
    union {
        vector(2,double) v;
        double d[2];
        } *vu = u, *vv = v, acc[2];

    /* Init some stuff. */
    acc[0].d[0] = 0.0; acc[0].d[1] = 0.0;
    acc[1].d[0] = 0.0; acc[1].d[1] = 0.0;

    /* Take in chunks of two by two doubles. */
    for ( i = 0 ; i < (n/2 & ~1) ; i += 2 ) {
        acc[0].v += vu[i].v * vv[i].v;
        acc[1].v += vu[i+1].v * vv[i+1].v;
        }
    w = acc[0].d[0] + acc[0].d[1] + acc[1].d[0] + acc[1].d[1];

    /* Catch leftovers (if any) */
    for ( i = n & ~3 ; i < n ; i++ )
        w += u[i] * v[i];

    return w;

}

void matmul2(int n, double v[], double A[], double u[])
{
    int i, j;
    union {
        vector(2,double) v;
        double d[2];
        } *vu = u, *vA, vi;

    bzero( u , sizeof(double) * n );

    for (i = 0; i < n; i++) {
        vi.d[0] = v[i];
        vi.d[1] = v[i];
        vA = &A[i*n];
        for ( j = 0 ; j < (n/2 & ~1) ; j += 2 ) {
            vu[j].v += vA[j].v * vi.v;
            vu[j+1].v += vA[j+1].v * vi.v;
            }
        for ( j = n & ~3 ; j < n ; j++ )
            u[j] += A[i*n+j] * v[i];
        }

}


void matmul3(int n, double A[], double v[], double u[])
{
    int i;

    for (i = 0; i < n; i++)
        u[i] = dot_product2( n , &A[i*n] , v );

}

void AvA(int n, double A[], double v[], double u[])
{
    double tmp[n] __attribute__ ((aligned (16)));
    matmul3(n, A, v, tmp);
    matmul2(n, tmp, A, u);
}


double spectral_game(int n)
{
    double *A;
    double u[n] __attribute__ ((aligned (16)));
    double v[n] __attribute__ ((aligned (16)));
    int i, j;

    /* Aligned allocation. */
    /* A = (double *)malloc(n*n*sizeof(double)); */
    if ( posix_memalign( (void **)&A , 4*sizeof(double) , sizeof(double) * n * n ) != 0 ) {
        printf( "spectral_game:%i: call to posix_memalign failed.\n" , __LINE__ );
        abort();
        }


    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            A[i*n+j] = Ac(i, j);
        }
    }


    for (i = 0; i < n; i++) {
        u[i] = 1.0;
    }
    for (i = 0; i < 10; i++) {
        AvA(n, A, u, v);
        AvA(n, A, v, u);
    }
    free(A);
    return sqrt(dot_product2(n, u, v) / dot_product2(n, v, v));
}

int main(int argc, char *argv[]) {
    int i, N = ((argc >= 2) ? atoi(argv[1]) : 2000);
    for ( i = 0 ; i < 10 ; i++ )
        printf("%.9f\n", spectral_game(N));
    return 0;
}

তিনটি সংস্করণ একই পতাকা এবং একই gccসংস্করণ দিয়ে সংকলিত হয়েছিল । মনে রাখবেন যে আরও সঠিক সময় পেতে আমি 0..9 থেকে একটি লুপে মূল ফাংশন কলটি গুটিয়ে রেখেছি।

$ time ./spectral_norm6 5500
1.274224153
...
real    0m22.682s
user    0m21.113s
sys 0m1.500s

$ time ./spectral_norm7 5500
1.274224153
...
real    0m21.596s
user    0m20.373s
sys 0m1.132s

$ time ./spectral_norm_vec 5500
1.274224153
...
real    0m21.336s
user    0m19.821s
sys 0m1.444s

সুতরাং "আরও ভাল" সংকলক পতাকা সহ, সি ++ সংস্করণটি ফোর্টরান সংস্করণটি সম্পাদন করে এবং হ্যান্ড-কোডেড ভেক্টরাইজ লুপগুলি কেবল একটি প্রান্তিক উন্নতি সরবরাহ করে। সি ++ সংস্করণটির জন্য এসেম্বলারের একটি তাত্ক্ষণিক দৃষ্টিভঙ্গি দেখায় যে মূল লুপগুলিও ভেক্টরাইজ করা হয়েছে, যদিও আরও আক্রমণাত্মকভাবে অনিয়ন্ত্রিত হয়ে পড়েছে।

আমার দ্বারা উত্পাদিত এসেম্বলারের দিকেও আমার নজর ছিল gfortranএবং এটি এখানে বিস্ময়কর: কোনও ভেক্টরাইজেশন নেই। আমি এই সত্যকে দায়ী করি যে এটি ব্যান্ডউইথের সীমাবদ্ধ হওয়ার কারণে সমস্যাটি কেবলমাত্র আর্কিটেকচারের তুলনায় সামান্য ধীর। প্রতিটি ম্যাট্রিক্সের গুণকগুলির জন্য, 230MB ডেটা ট্র্যাভারস করা হয়েছে, যা খুব বেশি পরিমাণে ক্যাশের সমস্ত স্তরকে সরিয়ে দেয়। আপনি যদি একটি ছোট ইনপুট মান ব্যবহার করেন, উদাহরণস্বরূপ 100, পারফরম্যান্সের পার্থক্যগুলি যথেষ্ট বেড়ে যায়।

পার্শ্ব-নোট হিসাবে, ভেক্টরাইজেশন, প্রান্তিককরণ এবং সংকলক পতাকাগুলি সম্পর্কে অবলম্বন না করে, সুনির্দিষ্ট সুস্পষ্ট অপ্টিমাইজেশনটি হ'ল একক-নির্ভুল গাণিতিকের প্রথম কয়েকটি পুনরাবৃত্তি গণনা করা, যতক্ষণ না আমরা ফলাফলের ~ 8 সংখ্যা পাই। একক-নির্ভুল নির্দেশাবলী কেবল দ্রুত নয়, তবে যে পরিমাণ মেমরির আশপাশে স্থানান্তর করতে হবে তাও অর্ধেক হয়ে যায়।


আপনার সময় জন্য অনেক ধন্যবাদ! আমি আশা করছিলাম তুমি উত্তর দিবে :) তাই আমি প্রথমে আপনার পতাকাগুলি ব্যবহার করার জন্য মেকফিলটিকে আপডেট করেছি। তারপরে আমি আপনার সি কোড বর্ণালী_নর্ম 8.c হিসাবে রেখেছি এবং README আপডেট করেছি। আমি আমার মেশিনে সময়গুলি আপডেট করেছি ( github.com/certik/spectral_norm/wiki/Timings ) এবং আপনি দেখতে পাচ্ছেন যে, সংকলক পতাকাগুলি আমার মেশিনে সি সংস্করণটি দ্রুততর করে না (যেমন গফট্রান এখনও জিতেছে), তবে আপনার সিমডি-ভেক্টরাইজড সংস্করণ মারধর করে।
ওঁদেজ এর্তিক

@ ওন্দেজিজারটিক: কৌতূহলের মাত্র বাইরে, আপনি কোন সংস্করণটি ব্যবহার করছেন gcc/ gfortranকরছেন? পূর্ববর্তী থ্রেডগুলিতে, বিভিন্ন সংস্করণ উল্লেখযোগ্যভাবে পৃথক ফলাফল দিয়েছে।
পেড্রো

আমি 4.6.1-9ubuntu3 ব্যবহার করি। আপনার কি ইন্টেল সংকলকগুলির অ্যাক্সেস রয়েছে? গফর্ট্রানের সাথে আমার অভিজ্ঞতা হ'ল কখনও কখনও এটি সর্বোত্তম কোড তৈরি করে না। আইফোোর্ট সাধারণত করে।
ওঁদেজ এর্তিক

1
@ ওন্ডিজেজারটেক: এখন ফলাফল আরও বেশি অর্থবহ! আমি matmul2অগ্রাহ্য করেছি যে ফোর্টরান সংস্করণটি শব্দার্থগতভাবে matmul3আমার সি সংস্করণের সাথে সমান । দুটি সংস্করণ সত্যিই এখন একই এবং এইভাবে gcc/ gfortran উচিত উভয়ের জন্য একই ফল, যেমন কেউ ফ্রন্ট-এন্ড / ভাষার এই ক্ষেত্রে অন্যান্য বেশী ভালো। gccকেবল আমাদের সুবিধার জন্য ভেক্টরাইজড নির্দেশনাগুলি কাজে লাগাতে পারে তার সুবিধা রয়েছে।
পেড্রো

1
@ সিজর্ডান 1: vector_sizeকোডটি প্ল্যাটফর্ম-স্বতন্ত্র করার জন্য আমি অ্যাট্রিবিউটটি ব্যবহার করা বেছে নিয়েছি , অর্থাৎ এই বাক্য gccগঠনটি ব্যবহার করে অন্যান্য প্ল্যাটফর্মগুলির জন্য ভেক্টরাইজ কোড তৈরি করতে সক্ষম হওয়া উচিত , যেমন আইবিএম পাওয়ার আর্কিটেকচারে আলটিভেক ব্যবহার করে।
পেড্রো

7

ব্যবহারকারীর 389 এর উত্তর মুছে ফেলা হয়েছে তবে আমাকে জানিয়ে দিন যে আমি দৃ camp়ভাবে তার শিবিরে রয়েছি: বিভিন্ন ভাষায় মাইক্রো-বেঞ্চমার্কের তুলনা করে আমরা কী শিখি তা দেখতে আমি ব্যর্থ। এটি আমার পক্ষে অবাক হওয়ার মতো কিছু নয় যে সি এবং ফোর্টরান এই মানদণ্ডে এটি কতটা সংক্ষিপ্ত করে দেওয়া হয়েছে একই রকম পারফরম্যান্স পেয়েছে। তবে বেঞ্চমার্কটিও বিরক্তিকর কারণ এটি দু'জন ডজন লাইনে সহজেই উভয় ভাষায় লেখা যেতে পারে। সফ্টওয়্যার দৃষ্টিকোণ থেকে, এটি কোনও প্রতিনিধি ক্ষেত্রে নয়: আমাদের 10,000 বা 100,000 লাইনের কোড রয়েছে এমন সফ্টওয়্যার এবং এর মধ্যে সংকলকরা কী করে সে সম্পর্কে আমাদের যত্ন নেওয়া উচিত। অবশ্যই, সেই স্কেলটিতে একজন দ্রুত অন্য জিনিসগুলি সন্ধান করতে পারে: সেই ভাষা এটির জন্য 10,000 টি লাইন প্রয়োজন হয় তবে ভাষা বিয়ের 50,000 প্রয়োজন। বা অন্যভাবে, আপনি যা করতে চান তার উপর নির্ভর করে। এবং হঠাৎ এটি '

অন্য কথায়, এটি আমার কাছে খুব বেশি গুরুত্বপূর্ণ নয় যে আমি আমার ফোর্টরান in 77 এ এটি বিকাশ করতে পারলে আমার অ্যাপ্লিকেশন ৫০% দ্রুত হতে পারে যদি পরিবর্তে এটি আমাকে সঠিকভাবে চালাতে এক মাস সময় নেয় তবে আমাকে 3 মাস সময় লাগে F77 এ। এখানে প্রশ্নের সমস্যাটি হ'ল এটি আমার দৃষ্টিভঙ্গিতে অনুশীলনের সাথে প্রাসঙ্গিক নয় এমন একটি দিক (স্বতন্ত্র কার্নেলগুলি) এর উপর দৃষ্টি নিবদ্ধ করে।


একমত। এটি খুব মূল্যবান, খুব ছোটখাট সম্পাদনা (-3 অক্ষর, +9 টি অক্ষর) বাদ দিয়ে আমি তার উত্তরের মূল অনুভূতির সাথে একমত হয়েছি। যতদূর আমি জানি, সি ++ / সি / ফোর্টরান সংকলক বিতর্ক কেবল তখনই গুরুত্বপূর্ণ যখন পারফরম্যান্স বর্ধনের জন্য প্রতিটি সম্ভাব্য অ্যাভিনিউ শেষ করে ফেলেছে, এ কারণেই, 99.9% লোকের জন্য, এই তুলনাগুলি গুরুত্বপূর্ণ নয়। আমি আলোচনাটি বিশেষভাবে আলোকিত হিসাবে খুঁজে পাই না, তবে আমি সাইটের কমপক্ষে একজন ব্যক্তির সাথে পরিচিত, যিনি পারফরম্যান্সের কারণে সি এবং সি ++ এর চেয়ে ফোর্টরানকে বেছে নেওয়ার পক্ষে সত্যতা দিতে পারেন, যার কারণে আমি বলতে পারি না এটি সম্পূর্ণরূপে অকেজো।
জেফ অক্সবেরি

4
আমি আপনার প্রধান বিন্দু সাথে একমত, কিন্তু আমি এখনও মনে করি যে এই আলোচনার দরকারী সেখানে হয় সেখানে আউট যারা এখনও একরকম বিশ্বাস একটি নম্বর আছে কিছু জাদু এক ভাষা "দ্রুত" অন্য চেয়ে তোলে যে, অভিন্ন কম্পাইলার ব্যবহার সত্ত্বেও ব্যাক-এন্ডের। আমি এই বিতর্কগুলিতে অবদান রাখি মূলত এই কল্পকাহিনীটি দূর করার চেষ্টা করার জন্য। পদ্ধতিটির হিসাবে, কোনও "প্রতিনিধি কেস" নেই, এবং আমার মতে, ম্যাট্রিক্স-ভেক্টর গুণমানের মতো সাধারণ কিছু নেওয়া ভাল জিনিস, কারণ এটি সংকলকরা তাদের কী করতে পারে বা না করতে পারে তা প্রদর্শনের জন্য যথেষ্ট স্থান দেয়।
পেড্রো

@ জিফঅক্সবেরি: অবশ্যই, আপনি সর্বদা এমন লোকদের খুঁজে পাবেন যারা কম বেশি ভালভাবে যুক্ত ও যুক্তিসঙ্গত কারণে অন্যের চেয়ে একটি ভাষা ব্যবহার করে। আমার প্রশ্ন, যদিও, ফোরট্রান কত দ্রুত হবে যদি কেউ যদি তথ্যের কাঠামোগুলি যে কোনও স্ট্রাকচার অবলম্বনকারী, অভিযোজিত সসীম উপাদানটি মিশে থাকে তবে সেগুলি ব্যবহার করে। ফোর্টরানে এটি বাস্তবায়নের জন্য বিশ্রী হয়ে উঠবে (যে কে সি ++ তে এটি প্রয়োগ করে তারা প্রত্যেকে এসটিএলকে প্রচুর ব্যবহার করে), ফোরট্রান কি এই ধরণের কোডের জন্য সত্যই দ্রুততর হবে যার কোনও আঁট লুপ নেই, অনেকগুলি ইন্ডিয়ারেশনস, প্রচুর আইএফ?
ওল্ফগ্যাং ব্যাঞ্জারথ

@ ওল্ফগ্যাংবাংয়ের্থ: যেমন আমি আমার প্রথম মন্তব্যে বলেছি, আমি আপনার সাথে এবং ব্যবহারকারীর সাথে একমত হয়েছি 389 (জনাথন দুরসি), সুতরাং আমাকে এই প্রশ্ন জিজ্ঞাসা করা অর্থহীন। এটি বলেছিল, যে কেউ বিশ্বাস করেন না এমন কাউকে আমন্ত্রণ জানাব যা আপনার প্রশ্নের উত্তর দেওয়ার জন্য ভাষার প্রয়োগ (সি ++ / সি / ফোর্টরানের মধ্যে) তাদের প্রয়োগের পারফরম্যান্সের জন্য গুরুত্বপূর্ণ। দুঃখের বিষয়, আমি সন্দেহ করি যে এই ধরণের বিতর্কটি সংকলক সংস্করণগুলির জন্য হতে পারে।
জেফ অক্সবেরি

@ জিফঅক্সবেরি: হ্যাঁ, এবং আমি স্পষ্টতই বোঝাতে চাইনি যে আপনাকে এই প্রশ্নের উত্তর দেওয়া দরকার।
ওল্ফগ্যাং ব্যাঙ্গারথ

5

দেখা যাচ্ছে যে আমি আমার সিস্টেমের গফর্ট্রান সংকলক সহ ফোর্টারান কোডের চেয়ে দ্রুত পাইথন কোড (বিএলএলএস অপারেশন করতে নাম্পি ব্যবহার করে) লিখতে পারি।

$ gfortran -o sn6a sn6a.f90 -O3 -march=native
    
    $ ./sn6a 5500
1.274224153
1.274224153
1.274224153
   1.9640001      sec per iteration

$ python ./foo1.py
1.27422415279
1.27422415279
1.27422415279
1.20618661245 sec per iteration

foo1.py:

import numpy
import scipy.linalg
import timeit

def specNormDot(A,n):
    u = numpy.ones(n)
    v = numpy.zeros(n)

    for i in xrange(10):
        v  = numpy.dot(numpy.dot(A,u),A)
        u  = numpy.dot(numpy.dot(A,v),A)

    print numpy.sqrt(numpy.vdot(u,v)/numpy.vdot(v,v))

    return

n = 5500

ii, jj = numpy.meshgrid(numpy.arange(1,n+1), numpy.arange(1,n+1))
A  = (1./((ii+jj-2.)*(ii+jj-1.)/2. + ii))

t = timeit.Timer("specNormDot(A,n)", "from __main__ import specNormDot,A,n")
ntries = 3

print t.timeit(ntries)/ntries, "sec per iteration"

এবং sn6a.f90, খুব হালকা পরিবর্তিত বর্ণালী_norm6.f90:

program spectral_norm6
! This uses spectral_norm3 as a starting point, but does not use the
! Fortrans
! builtin matmul and dotproduct (to make sure it does not call some
! optimized
! BLAS behind the scene).
implicit none

integer, parameter :: dp = kind(0d0)
real(dp), allocatable :: A(:, :), u(:), v(:)
integer :: i, j, n
character(len=6) :: argv
integer :: calc, iter
integer, parameter :: niters=3

call get_command_argument(1, argv)
read(argv, *) n

allocate(u(n), v(n), A(n, n))
do j = 1, n
    do i = 1, n
        A(i, j) = Ac(i, j)
    end do
end do

call tick(calc)

do iter=1,niters
    u = 1
    do i = 1, 10
        v = AvA(A, u)
        u = AvA(A, v)
    end do

    write(*, "(f0.9)") sqrt(dot_product2(u, v) / dot_product2(v, v))
enddo

print *, tock(calc)/niters, ' sec per iteration'

contains

pure real(dp) function Ac(i, j) result(r)
integer, intent(in) :: i, j
r = 1._dp / ((i+j-2) * (i+j-1)/2 + i)
end function

pure function matmul2(v, A) result(u)
! Calculates u = matmul(v, A), but much faster (in gfortran)
real(dp), intent(in) :: v(:), A(:, :)
real(dp) :: u(size(v))
integer :: i
do i = 1, size(v)
    u(i) = dot_product2(A(:, i), v)
end do
end function

pure real(dp) function dot_product2(u, v) result(w)
! Calculates w = dot_product(u, v)
real(dp), intent(in) :: u(:), v(:)
integer :: i
w = 0
do i = 1, size(u)
    w = w + u(i)*v(i)
end do
end function

pure function matmul3(A, v) result(u)
! Calculates u = matmul(v, A), but much faster (in gfortran)
real(dp), intent(in) :: v(:), A(:, :)
real(dp) :: u(size(v))
integer :: i, j
u = 0
do j = 1, size(v)
    do i = 1, size(v)
        u(i) = u(i) + A(i, j)*v(j)
    end do
end do
end function

pure function AvA(A, v) result(u)
! Calculates u = matmul2(matmul3(A, v), A)
! In gfortran, this function is sligthly faster than calling
! matmul2(matmul3(A, v), A) directly.
real(dp), intent(in) :: v(:), A(:, :)
real(dp) :: u(size(v))
u = matmul2(matmul3(A, v), A)
end function

subroutine tick(t)
    integer, intent(OUT) :: t

    call system_clock(t)
end subroutine tick

! returns time in seconds from now to time described by t 
real function tock(t)
    integer, intent(in) :: t
    integer :: now, clock_rate

    call system_clock(now,clock_rate)

    tock = real(now - t)/real(clock_rate)
end function tock
end program

1
গালে জিহ্বা, আমার ধারণা?
রবার্ট হার্ভে

প্রশ্নের উত্তর না দেওয়ার জন্য -1, তবে আমি মনে করি আপনি এটি ইতিমধ্যে জানেন।
পেড্রো

আকর্ষণীয়, আপনি গেফট্রানের কোন সংস্করণ ব্যবহার করেছিলেন এবং আপনি পেড্রোর পতাকা সহ সংগ্রহস্থলীতে উপলব্ধ সি কোডটি পরীক্ষা করে দেখেছেন?
অরন আহমদিয়া

1
আসলে, আমি মনে করি এটি এখন আরও পরিষ্কার হয়ে গেছে, ধরে নিই যে আপনি ব্যঙ্গাত্মক হয়ে উঠছেন না।
রবার্ট হার্ভে

1
এই পোস্টে, এবং অন্যান্য প্রশ্ন বা পোস্টের মধ্যে কেউ সাল থেকে, ভাল করতে এমনভাবে Aron দ্বারা সম্পাদিত হচ্ছে তার মতামত মেলে, যদিও আমার পুরো পয়েন্ট যে সব পোস্ট দিয়ে লেবেল করা উচিত ঠিক যেমন "এই ফলাফল অর্থহীন হল" সতর্কতা, আমি এটি মুছে ফেলছি।

3

ইন্টেল সংকলকগুলির সাথে এটি পরীক্ষা করা হয়েছে। ১১.১ এর সাথে (-প্রস্তর, অন্তর্ভুক্ত -O3), এবং 12.0 (-O2) সহ দ্রুততমগুলি 1,2,6,7, এবং 8 (অর্থাত্ "সরলতম" ফোর্টরান এবং সি কোড এবং হ্যান্ড-ভেক্টরাইজড সি) রয়েছে - এগুলি একে অপরের থেকে ~ 1.5s এ পৃথক হয়। পরীক্ষা 3 এবং 5 (একটি ফাংশন হিসাবে অ্যারে সহ) ধীর হয়; # 4 আমি সংকলন করতে পারিনি।

বেশ উল্লেখযোগ্যভাবে, -২-এর পরিবর্তে 12.0 এবং -O3 দিয়ে সংকলন করা হলে, প্রথম 2 ("সর্বাধিক") ফোর্টরান কোডগুলি একটি লট (1.5 -> 10.2 সেকেন্ড।) ধীর করে দেয় - আমি এই প্রথম এমন কিছু দেখছি না এটি, তবে এটি সবচেয়ে নাটকীয় উদাহরণ হতে পারে। যদি বর্তমান রিলিজের ক্ষেত্রে এটি এখনও অবধি থাকে তবে আমি মনে করি এটি ইন্টেলের কাছে জানানো ভাল ধারণা হবে কারণ স্পষ্টতই এটির চেয়ে সহজ ক্ষেত্রে তাদের অপ্টিমাইজেশনে খুব ভুল হচ্ছে।

অন্যথায় আমি জোনাথনের সাথে একমত যে এটি কোনও তথ্যবহুল অনুশীলন নয় :)


এটি যাচাই করার জন্য ধন্যবাদ! এটি আমার অভিজ্ঞতার সত্যতা নিশ্চিত করে, যে গফর্ট্রান এখনও পুরোপুরি পরিপক্ক নয়, কারণ কোনও কারণে ম্যাটমুল অপারেশনটি ধীর গতিতে রয়েছে। সুতরাং আমার জন্য উপসংহারটি হ'ল ম্যাটমুল ব্যবহার করা এবং ফোর্টরান কোডটি সহজ রাখা।
ওন্দেজ এর্ত্তেক

অন্যদিকে, আমার কাছে মনে হয় যে সমস্ত ম্যাথামুল () কলগুলি স্বয়ংক্রিয়ভাবে বিএলএএস কলগুলিতে রূপান্তর করার জন্য গফর্ট্রানের একটি কমান্ড লাইন বিকল্প রয়েছে (সম্ভবত ডট_প্রডাক্ট ()ও নিশ্চিত নয়)। যদিও এটি চেষ্টা করেন নি।
ল্যাক্স্সি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.