এই প্রশ্নটি দুটি আলোচনার একটি বর্ধন যা সম্প্রতি " এইচপিসির জন্য সি ++ বনাম ফোর্টরান " এর উত্তরে উঠে এসেছিল । এবং এটি একটি প্রশ্নের চেয়ে কিছুটা চ্যালেঞ্জ ...
ফোর্টরানের পক্ষে সর্বাধিক শোনা যুক্তিগুলির মধ্যে একটি হল যে সংকলকগুলি আরও ভাল। যেহেতু বেশিরভাগ সি / ফোর্টরান সংকলক একই পিছনের অংশটি ভাগ করে, তাই উভয় ভাষায় শব্দার্থগত সমতুল্য প্রোগ্রামগুলির জন্য উত্পন্ন কোডটি সমান হওয়া উচিত। যে কেউ তর্ক করতে পারে, তবে সি / ফোর্টরান কমপ্লায়ারটি অনুকূলিতকরণের জন্য আরও কম / কম সহজ।
সুতরাং আমি একটি সাধারণ পরীক্ষা করার চেষ্টা করার সিদ্ধান্ত নিয়েছি: আমি daxpy.f এবং daxpy.c এর একটি অনুলিপি পেয়েছি এবং সেগুলি gfortran / gcc দিয়ে সংকলন করেছি।
Daxpy.c এখন daxpy.f এর একটি f2c অনুবাদ (স্বয়ংক্রিয়ভাবে উত্পন্ন কোড, হেক হিসাবে কুশ্রী), সুতরাং আমি সেই কোডটি নিয়েছি এবং এটি কিছুটা সাফ করেছি (ডেক্সপি_সি এর সাথে মিলিত), যা মূলত অন্তঃস্থলীয় লুপটি পুনরায় লেখার জন্য বোঝানো হয়েছিল
for ( i = 0 ; i < n ; i++ )
dy[i] += da * dx[i];
অবশেষে, আমি সিসিএসির ভেক্টর সিনট্যাক্স ব্যবহার করে এটি পুনরায় লিখেছি (daxpy_cvec লিখুন):
#define vector(elcount, type) __attribute__((vector_size((elcount)*sizeof(type)))) type
vector(2,double) va = { da , da }, *vx, *vy;
vx = (void *)dx; vy = (void *)dy;
for ( i = 0 ; i < (n/2 & ~1) ; i += 2 ) {
vy[i] += va * vx[i];
vy[i+1] += va * vx[i+1];
}
for ( i = n & ~3 ; i < n ; i++ )
dy[i] += da * dx[i];
নোট করুন যে আমি দৈর্ঘ্য 2 এর ভেক্টর ব্যবহার করি (এগুলিই এসএসই 2 দ্বারা অনুমোদিত) এবং আমি একবারে দুটি ভেক্টর প্রসেস করি। এটি কারণ অনেক আর্কিটেকচারে, আমাদের ভেক্টর উপাদানগুলির তুলনায় আমাদের আরও গুণক ইউনিট থাকতে পারে।
"-O3 -Wall -msse2 -march = নেটিভ-ফার্স্ট-ম্যাথ-ফোমিট-ফ্রেম-পয়েন্টার -মালিগান-ডাবল -স্ট্রিক্ট-এলিয়াসিং" এর সাহায্যে সমস্ত কোডগুলি গফর্ট্রান / জিসিসি সংস্করণ 4.5 ব্যবহার করে সংকলিত হয়েছিল। আমার ল্যাপটপে (Intel Core i5 CPU, M560, 2.67GHz) আমি নিম্নলিখিত আউটপুটটি পেয়েছি:
pedro@laika:~/work/fvsc$ ./test 1000000 10000
timing 1000000 runs with a vector of length 10000.
daxpy_f took 8156.7 ms.
daxpy_f2c took 10568.1 ms.
daxpy_c took 7912.8 ms.
daxpy_cvec took 5670.8 ms.
সুতরাং মূল ফোরট্রান কোডটি 8.1 সেকেন্ডের চেয়ে কিছুটা বেশি সময় নেয়, এর স্বয়ংক্রিয় অনুবাদটি 10.5 সেকেন্ড সময় নেয়, নিষ্পাপ সি বাস্তবায়ন এটি 7.9 সালে করে এবং স্পষ্টভাবে ভেক্টরাইজড কোডটি এটি 5.6-এ প্রান্তিকভাবে কম করে।
এটি ফোরট্রান সিভিল সি বাস্তবায়নের তুলনায় কিছুটা ধীর এবং ভেক্টরাইজড সি প্রয়োগের তুলনায় 50% ধীর গতির হয়ে যাচ্ছে।
সুতরাং এখানে প্রশ্নটি রয়েছে: আমি একজন স্থানীয় সি প্রোগ্রামার এবং তাই আমি পুরোপুরি আত্মবিশ্বাসী যে এই কোডটিতে আমি একটি ভাল কাজ করেছি, তবে ফোর্টরান কোডটি সর্বশেষে ১৯৯৩ সালে ছুঁয়ে গিয়েছিল এবং তাই এটি সম্ভবত কিছুটা পুরানো হতে পারে। যেহেতু আমি এখানে অন্যদের মতো ফোর্টরানে কোডিংয়ের মতো স্বাচ্ছন্দ্য বোধ করি না, তাই কেউ কি আরও ভাল কাজ করতে পারেন, যেমন দুটি সি সংস্করণের যে কোনওটির তুলনায় আরও প্রতিযোগিতামূলক?
এছাড়াও, কেউ কি এই পরীক্ষাটি আইসিসি / ifort দিয়ে চেষ্টা করতে পারেন? ভেক্টর সিনট্যাক্স সম্ভবত কাজ করবে না, তবে আমি সেখানে উদাসীন সি সংস্করণটি কীভাবে আচরণ করে তা জানতে আগ্রহী। এক্সএলসি / এক্সএলএফ চারপাশে থাকা কারও পক্ষে একই কাজ।
আমি উত্স এবং একটি মেকফিল এখানে আপলোড করেছি । সঠিক সময় পেতে, আপনার সিপিইউতে হার্জেডের সংখ্যার জন্য পরীক্ষামূলক সিপিইউপিপিএসে সিপিইউপিপিএস সেট করুন। আপনি যদি সংস্করণগুলির কোনওর মধ্যে কোনও উন্নতি পেয়ে থাকেন তবে দয়া করে সেগুলি এখানে পোস্ট করুন!
হালনাগাদ:
আমি অনলাইনে ফাইলগুলিতে স্টালির পরীক্ষার কোড যুক্ত করেছি এবং এটি একটি সি সংস্করণ দিয়ে পরিপূরক করেছি। পূর্ববর্তী পরীক্ষার সাথে সামঞ্জস্য রাখতে আমি 10'000 দৈর্ঘ্যের ভেক্টরগুলিতে 1'000'000 লুপগুলি করতে প্রোগ্রামগুলি সংশোধন করেছি (এবং কারণ আমার মেশিন স্টালির মূল হিসাবে 1'000'000'000 দৈর্ঘ্যের ভেক্টর বরাদ্দ করতে পারেনি কোড)। যেহেতু সংখ্যাগুলি এখন কিছুটা ছোট, তাই আমি -par-threshold:50
সংকলকটিকে সমান্তরাল হওয়ার সম্ভাবনা তৈরি করতে বিকল্পটি ব্যবহার করেছি used ব্যবহৃত আইসিসি / আইফোর্ট সংস্করণটি 12.1.2 20111128 এবং ফলাফলগুলি নিম্নরূপ
pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=1 time ./icctest_c
3.27user 0.00system 0:03.27elapsed 99%CPU
pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=1 time ./icctest_f
3.29user 0.00system 0:03.29elapsed 99%CPU
pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=2 time ./icctest_c
4.89user 0.00system 0:02.60elapsed 188%CPU
pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=2 time ./icctest_f
4.91user 0.00system 0:02.60elapsed 188%CPU
সংক্ষেপে, ফলাফলগুলি সমস্ত ব্যবহারিক উদ্দেশ্যে, সি এবং ফোর্টরান উভয় সংস্করণের জন্য অভিন্ন এবং উভয় কোডই স্বয়ংক্রিয়ভাবে সমান্তরাল হয়। নোট করুন যে আগের পরীক্ষার তুলনায় দ্রুতগতির সময়গুলি সিঙ্গল-স্পষ্টতা ভাসমান পয়েন্ট গাণিতিক ব্যবহারের কারণে হয়!
হালনাগাদ:
যদিও প্রমাণের বোঝা এখানে চলেছে তা আমি সত্যিই পছন্দ করি না, তবে আমি স্টির ম্যাট্রিক্সের গুণকে উদাহরণস্বরূপ কোড করেছি এবং এটি ওয়েবে ফাইলগুলিতে যুক্ত করেছি । এক এবং দুটি সিপিইউয়ের জন্য ট্রিপল লুপের ফলাফল এখানে রয়েছে:
pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=1 time ./mm_test_f 2500
triple do time 3.46421700000000
3.63user 0.06system 0:03.70elapsed 99%CPU
pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=1 time ./mm_test_c 2500
triple do time 3.431997791385768
3.58user 0.10system 0:03.69elapsed 99%CPU
pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=2 time ./mm_test_f 2500
triple do time 5.09631900000000
5.26user 0.06system 0:02.81elapsed 189%CPU
pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=2 time ./mm_test_c 2500
triple do time 2.298916975280899
4.78user 0.08system 0:02.62elapsed 184%CPU
নোট করুন যে cpu_time
ফোর্টরান সিপিইউয়ের সময় পরিমাপ করে দেয়াল-ঘড়ির সময় নয়, তাই আমি কলগুলিকে time
2 টি সিপিইউয়ের সাথে তুলনা করতে গুটিয়ে রেখেছি । ফলাফলগুলির মধ্যে সত্যিকারের কোনও পার্থক্য নেই, কেবল দুটি সংস্করণে সি সংস্করণটি আরও ভাল করে।
এখন matmul
কমান্ডের জন্য, অবশ্যই কেবল ফোর্টরানে কারণ এই অভ্যন্তরীণটি সি তে পাওয়া যায় না:
pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=1 time ./mm_test_f 2500
matmul time 23.6494780000000
23.80user 0.08system 0:23.91elapsed 99%CPU
pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=2 time ./mm_test_f 2500
matmul time 26.6176640000000
26.75user 0.10system 0:13.62elapsed 197%CPU
কি দারুন. এটা একেবারে ভয়ানক। আমি কী ভুল করছি তা কেউ জানতে পারে, বা ব্যাখ্যা করতে পারে যে কেন এই অভ্যন্তরীণতা এখনও কোনও ভাল জিনিস?
আমি dgemm
ইনটেল এমকেএল একই ফাংশনে লাইব্রেরি কল হওয়ায় আমি বেঞ্চমার্কে কলগুলি যুক্ত করিনি ।
ভবিষ্যতের পরীক্ষাগুলির জন্য, কেউ ফর্ট্রানের তুলনায় সি-তে ধীরতম বলে পরিচিত উদাহরণটি কি প্রস্তাব করতে পারেন ?
হালনাগাদ
matmul
ছোট ম্যাট্রিকগুলিতে স্পষ্টতাত্ত্বিক ম্যাট্রিক্স পণ্যটির চেয়ে অন্তর্নিহিত "ম্যাগনিটুয়ের ক্রম" হ'ল স্ট্যালির দাবী যাচাই করতে , আমি তার নিজস্ব কোডটি উভয় পদ্ধতি ব্যবহার করে 100x100 আকারের ম্যাট্রিকগুলিকে প্রতিটি 10'000 বার ব্যবহার করে পরিবর্তন করেছি। এক এবং দুটি সিপিইউতে ফলাফলগুলি নিম্নরূপ:
pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=1 time ./mm_test_f 10000 100
matmul time 3.61222500000000
triple do time 3.54022200000000
7.15user 0.00system 0:07.16elapsed 99%CPU
pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=2 time ./mm_test_f 10000 100
matmul time 4.54428400000000
triple do time 4.31626900000000
8.86user 0.00system 0:04.60elapsed 192%CPU
হালনাগাদ
গ্রিসু উল্লেখ করে সঠিক যে, অপ্টিমাইজেশন ছাড়াই, জিসিসি জটিল সংখ্যায় ক্রিয়াকলাপগুলি লাইব্রেরি ফাংশন কলগুলিতে রূপান্তরিত করে যখন গফর্ট্রান তাদের কয়েকটি নির্দেশিকায় ইনলাইন করে।
সি সংকলক বিকল্পটি -fcx-limited-range
সেট করা থাকলে একই, কমপ্যাক্ট কোড উত্পন্ন করবে , অর্থাত্ সংকলককে মধ্যবর্তী মানগুলিতে সম্ভাব্য ওভার / নিম্ন-প্রবাহকে উপেক্ষা করার জন্য নির্দেশ দেওয়া হয়েছে। এই বিকল্পটি কোনওভাবে গফর্ট্রানে ডিফল্টরূপে সেট করা আছে এবং ভুল ফলাফল হতে পারে। অত্যাচার -fno-cx-limited-range
gfortran কিছু পরিবর্তন হয়নি।
সুতরাং এটি আসলে সংখ্যার গণনার জন্য গফর্ট্রান ব্যবহারের বিরুদ্ধে একটি যুক্তি : জটিল মানগুলির উপর অপারেশনগুলি প্রবাহিত / নিচে প্রবাহিত হতে পারে এমনকি সঠিক ফলাফলগুলি ভাসমান-বিন্দু সীমার মধ্যে থাকলেও। এটি আসলে ফোর্টরান স্ট্যান্ডার্ড। জিসিসি বা সাধারণভাবে সি 99 এ ডিফল্টরূপে অন্যথায় নির্দিষ্ট না করা পর্যন্ত কাজগুলি কঠোরভাবে করা (আইইইই -754 অনুগামী পড়ুন)।
অনুস্মারক: দয়া করে মনে রাখবেন যে মূল প্রশ্নটি ছিল ফোর্টরান সংকলক সি সিগেলারগুলির চেয়ে ভাল কোড উত্পাদন করে কিনা। এক ভাষার অন্য ভাষার সাধারণ গুণাগুণ সম্পর্কে এটি আলোচনার জায়গা নয়। আমি যে বিষয়ে আগ্রহী তা হ'ল যদি কেউ স্পষ্টভাবে ভেক্টরাইজেশন ব্যবহার করে সি-এর মতো দক্ষতার মতো একটি ড্যাক্সি তৈরির জন্য গফট্রানকে কোক্সিং করার কোনও উপায় খুঁজে পায় তবে এটি কেবলমাত্র সিমড অপ্টিমাইজেশনের জন্যই সংকলকটির উপর নির্ভর করার সমস্যাগুলির উদাহরণ দেয় বা একটি যে ক্ষেত্রে কোনও ফোর্টরান তার সি প্রতিরূপ তৈরি করে।