اختبار الخوارزمات المختلفة تم على جهاز واحد (جهازي). أما بالنسبة لاختبار #C و ++C فنحن ننتظر نتائج البرنامج المرفق في جهاز خالد.
و أنا أتفق معك أن فروقات الأداء هذه لا معنى لها في العديد من السيناريوهات.
اختبار الخوارزمات المختلفة تم على جهاز واحد (جهازي). أما بالنسبة لاختبار #C و ++C فنحن ننتظر نتائج البرنامج المرفق في جهاز خالد.
و أنا أتفق معك أن فروقات الأداء هذه لا معنى لها في العديد من السيناريوهات.
بصراحة عجبتني الفكرة فقلت نسوي بورت لسكربت الجافا إلى السي بلاس بلاس ،
هذه عملي :
#include <iostream>
#include <ctime>
using namespace std;
/* A program to solve Poject Euler problem 92 */
/* Calculate the square of the digits of an integer */
static int SquareDigits(int i)
{
int res = 0;
int cd;
while (i > 9)
{
cd = i % 10;
res = res + (cd * cd);
i = i / 10;
}
res = res + (i * i);
return res;
}
/* Determine if an integer culminates in 89 eventually (only other finish
* state is 1). */
static bool End89(int i)
{
i = SquareDigits(i);
while (!(i == 1))
{
i = SquareDigits(i);
if (i == 89)
{
return true;
}
}
return false;
}
/* Given an integer, determine the maximum value of it's digits squared. */
static int MaxValue(int i)
{
int max = 81;
while (i > 9)
{
i = i / 10;
max = max + 81;
}
return max;
}
/* An initialise method to set all the values in an array based on a known
* size. A shorter lookup as all other values will end up at one of these
* so predetermine them all to save recalculation. */
static void Init(int tsize, bool vals[] )
{
while (tsize > 0)
{
vals[tsize - 1] = End89(tsize);
tsize = tsize - 1;
}
}
/* The main method that does most of the work. */
int main()
{
clock_t start = clock();
// The limit for the Euler Problem.
int limit = 9999999;
// Set the array size to be the maximum value for the square of
// the number of digits in the limit.
int arsize = MaxValue(limit);
// Initialise the count of the ones that end in 89.
int count = 0;
// Create the array and then initialise it.
bool vals[arsize];
Init(arsize, vals);
// Count down from the limit and if the number ends in 89 (based on
// pre-calculated values) then increment the count.
while (limit > 0)
{
if (vals[SquareDigits(limit) - 1])
{
count = count + 1;
}
limit = limit - 1;
}
// Print the result!
cout << ( ( clock() - start ) / (double)CLOCKS_PER_SEC ) << '\n';
cout << "Result is: " << count << '\n';
return 0;
}بالنسبة للنتيجة فأنا استخدم نظام أوبنتو لينكس الإصدارة 8.04 و g++ الإصدارة 4.2 و مونو 1.9
الوقت المستغرق في سكربت سي شارب هو :
1.896796 - 1.934714 - 1.900069
الوقت المستغرق في سكربت السي بلاس بلاس :
1.18 - 1.16 - 1.17
الوقت المستغرق في سكربت جافا :
1.999 - 2.016 - 2.020
أتمنى لو احد يشاركنا بسكربت بايثون مع اطيب تحية
تم تعديل هذه المشاركة بواسطة OMLX في 7 يونيو 2009 في 14:50
يبدو أن محاولاتي في استخدام اللامبدا باءت بالفشل. هذا الكود يختبر خمس خوارزميات. الأولى هي الـiterative التي استخدمناها في الحلول الأخيرة، و هي ما زالت الأسرع. ثم هناك حل recursive لا لشئ سوى أنني أحب الـrecursion :P . ثم هناك ثلاث محاولات باللامبدا كلها كانت أبطأ من الأولى و أقرب من الثانية، لأنها في الواقع كلها حلول recursive. واجهت عدة مشاكل في محاولة كتابة لامبدا تنادي نفسها و وجدت ثلاثة حلول. الحل الثالث مكنني من كتابة جملة لامبدا لطيفة جداً و لكنها أيضاً الأبطأ و تعتمد على ما يدعى بـY fixed-point combinator التي لن أدعي أنني فهمتها فهماً كاملاً :lol: . أعتقد أن سبب بطء الحلول الـfunctional التي استخدمتها هي انحصار فكري بالحلول الـrecursive الخاصة باللغات الـimperative، فلو كان لدى أحد حل أفضل نرجو ذكره.
البرنامج مرفق.
المرجع الذي استخدمته لعمل Recursive Lambda
http://blogs.msdn.com/wesdyer/archive/2007...rsion-in-c.aspx
الكود
using System;
using System.Collections.Generic;
namespace Project_Euler
{
class Program
{
static void Main(string[] args)
{
int iterationCount = 3;
DateTime rightNow;
uint count;
uint max = 9999999;
for (int current = 1; current <= iterationCount; current++)
{
Console.WriteLine("Iteration #" + current.ToString());
Console.WriteLine("Iterative method:");
rightNow = DateTime.Now;
count = 0;
for (uint i = max; i > 0; i--)
if (EndsIn89Iterator(i)) count++;
Console.WriteLine(DateTime.Now.Subtract(rightNow).ToString());
Console.WriteLine(count);
Console.WriteLine();
Console.WriteLine("Recursive method:");
rightNow = DateTime.Now;
count = 0;
for (uint i = max; i > 0; i--)
if (EndsIn89Recursive(i)) count++;
Console.WriteLine(DateTime.Now.Subtract(rightNow).ToString());
Console.WriteLine(count);
Console.WriteLine();
Console.WriteLine("Lambda method 1:");
rightNow = DateTime.Now;
count = 0;
for (uint i = max; i > 0; i--)
if (EndsIn89Lambda1(i)) count++;
Console.WriteLine(DateTime.Now.Subtract(rightNow).ToString());
Console.WriteLine(count);
Console.WriteLine();
Console.WriteLine("Lambda method 2:");
rightNow = DateTime.Now;
count = 0;
for (uint i = max; i > 0; i--)
if (EndsIn89Lambda2(i)) count++;
Console.WriteLine(DateTime.Now.Subtract(rightNow).ToString());
Console.WriteLine(count);
Console.WriteLine();
Console.WriteLine("Lambda method 3:");
rightNow = DateTime.Now;
count = 0;
for (uint i = max; i > 0; i--)
if (EndsIn89Lambda3(i)) count++;
Console.WriteLine(DateTime.Now.Subtract(rightNow).ToString());
Console.WriteLine(count);
Console.WriteLine();
Console.WriteLine("-------------------------");
}
Console.WriteLine();
Console.WriteLine("Done.");
Console.ReadKey();
}
#region Iterator
private static uint SquareDigits(uint number)
{
uint total = 0;
uint digit;
while (number > 9)
{
digit = number % 10;
total = total + (digit * digit);
number = number / 10;
}
total = total + (number * number);
return total;
}
static bool EndsIn89Iterator(uint number)
{
number = SquareDigits(number);
while (!(number == 1))
{
number = SquareDigits(number);
if (number == 89)
{
return true;
}
}
return false;
}
#endregion
#region Recursive
static bool EndsIn89Recursive(uint number)
{
uint result = SquareDigitsRecursive(number);
while (result != 89 && result != 1)
result = SquareDigitsRecursive(result);
return (result == 89);
}
static uint SquareDigitsRecursive(uint number)
{
uint result = 0;
uint digit;
if (number > 9)
{
digit = number % 10;
result += (digit * digit);
return result + SquareDigitsRecursive(number / 10);
}
else
{
digit = number % 10;
result += digit * digit;
return result;
}
}
#endregion
#region Lambda 1
static bool EndsIn89Lambda1(uint number)
{
Func<uint, uint> Square = x => x * x;
Func<uint, uint> SquareDigits = null;
SquareDigits = x =>
{
uint result;
var digit = (x % 10);
result = Square(digit);
if (x > 9)
return SquareDigits(x / 10) + result;
else
return result;
};
Func<uint, bool> EndsIn89 = x =>
{
uint result;
result = SquareDigits(x);
while (result != 89 && result != 1)
result = SquareDigits(result);
return (result == 89);
};
return EndsIn89(number);
}
#endregion
#region Lambda 2
delegate R Recursive<A, R>(Recursive<A, R> r, A a);
static bool EndsIn89Lambda2(uint number)
{
Func<uint, uint> Square = x => x * x;
Recursive<uint, uint> SquareDigits = (function, x) =>
{
uint result;
var digit = (x % 10);
result = Square(digit);
if (x > 9)
return function(function, x / 10) + result;
else
return result;
};
Func<uint, bool> EndsIn89 = x =>
{
uint result;
result = SquareDigits(SquareDigits, x);
while (result != 89 && result != 1)
result = SquareDigits(SquareDigits, result);
return (result == 89);
};
return EndsIn89(number);
}
#endregion
#region Lambda 3
static Func<A, R> Y<A, R>(Func<Func<A, R>, Func<A, R>> f)
{
Func<A, R> g = null;
g = f(a => g(a));
return g;
}
static bool EndsIn89Lambda3(uint number)
{
Func<uint, uint> Square = x => x * x;
Func<uint, uint> SquareDigits = Y<uint, uint>
(f => x => x > 9 ? Square(x % 10) + f(x / 10) : Square(x % 10));
Func<uint, bool> EndsIn89 = Y<uint, bool>
(f => x => (x != 89 && x != 1) ? f(SquareDigits(x)) : x == 89);
return EndsIn89(number);
}
#endregion
}
}السلام عليكم ...
يبدو أن الموضوع انقلب إلى حقل تجارب نووية :lol:
عموماً هذه هي تجربتي لكتابة الكود الذي أتى به الأخ متميز :)
رغم أني لم أفهم الخوارزمية بشكل كامل بعد إلا أنه لا مانع من رؤية النتائج :)
جهازي يعمل بـ Vista, و أستخدم VC 2008 express,
سميت الملف التنفيذي لـ ++C بـ Cxx و الملف التنفيذي المكتوب بـ #C بـ CSharp, و هذا هو الكود بـ ++C ::-
#include <ctime>
#include <iostream>
int squareOfDigits(int number)
{
int sum = 0, reminder = 0;
while(number > 0)
{
reminder = number % 10;
sum += reminder * reminder;
number /= 10;
}
return sum;
}
bool end89(int number)
{
while(number != 1)
{
number = squareOfDigits(number);
if(number == 89)
return true;
}
return false;
}
inline int maxValue(int number)
{
int max = 81;
while(number > 9)
{
number /= 10;
max = max + 81;
}
return max;
}
void init(bool values[], int valSize)
{
while(valSize > 0)
{
values[valSize-1] = end89(valSize);
valSize--;
}
}
int main()
{
clock_t start = clock();
int limit = 9999999, count = 0;
int valSize = maxValue(limit);
bool* values = new bool[valSize];
init(values, valSize);
while(limit > 0)
{
if(values[squareOfDigits(limit)-1] == true)
count++;
limit--;
}
delete[] values;
std::cout << (clock() - start)/static_cast<double>(CLOCKS_PER_SEC) << std::endl;
std::cout << "Result = " << count;
return 0;
}و هذه نتائج برنامج الـ C#
و هذه نتائج برنامج الـ ++C
بالمناسبة هذه النتائج لا تعني أي شيء عملياً,
كانت تجربة لا أكثر, و على جهازي يحتاج برنامج #C إلى أكثر من ثلاثة أضعاف الوقت بقليل تقريباً...
مع العلم أن مترجم Microsoft فيه الكثير من خيارات الـ Optimization, و لكن باعتقادي أنها ستؤثر بشكل هامشي في برنامج صغير كهذا,
و كود البرنامج مترجم لمعالج 386 لأضمن عمله على أي جهاز :)
بالمناسبة أخي OMLX تأكد أنك تترجم بشكل نهائي, و ليس للـ Debugging ...
و الملفات التنفيذية للغتين موجودة في المرفقات ....
تحياتي ...
تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 7 يونيو 2009 في 17:13
لأصحاب القلوب القوية فقط!
قمت بإعادة كتابة الدالة maxValue باستخدام الـ Templates, و هي لغة Functional داخل ++C كعرض لأحد أساليب ++C في البرمجة لمن يحب الإطلاع :)
ستجد ملف يسمى Meta.cpp يحتوي على تعريف الدالة maxVal, إذا لم تكن تعرف الـ Metaprogramming من قبل في ++C, فلا تقلق,
كل ما في الأمر, عبارة عن دالة تنفذ وقت الترجمة و يعاد بالقيمة قبل ترجمة البرنامج,
الدالة عبارة عن Recursion و الـ Special Cases الخاصة بالـ Recursion على شكل Pattern Matching (؟؟؟؟ لا أدري كيف تقال بالعربية :wacko: )
عموماً للتجربة.................و الوقت لن يختلف كثيراً عن البرنامج الأصلي لأن القيمة التي تعيدها الدالة maxValue نستخدمها مرة واحدة في برنامجنا الأصلي,
تحياتي ...
ليس لدي تفسير منطقي حقيقة للسرعة العجيبة لبرنامج #C لديك!
انظر, هذه نتائج الـ Debug و الـ Release من المشروع الذي وضعته أنت في مشاركة سابقة....
نسخة الـ Debugging أبطأ بقليل و هذا شيء طبيعي,
الآن هناك شيء منطقي و هناك شيء لم أستطع تفسيره حقيقة, ربما هناك شيء لم أفهمه حتى الآن حول #C,
على جهازي عمل برنامج ++C في 0.34 تقريباً, و لديك عمل في 0.43 تقريباً, و أذكر أنك قلت أن تقييم جهازك حسب Vista Experience Index هو 5.1,
جهازي تقييمه كالتالي ::
و هو ما يفسر الفرق البسيط ربما بين التجربة لديك و التجربة لدي,
ما لم أفهمه حتى الآن هو السرعة الغريبة لبرنامج الـ #C على جهاز مواصفاته أقل من مواصفات جهازي....
لدي يعمل خلال 1.2 ثانية, و لديك يعمل برنامج #C خلال 0.37 بفارق غير ملحوظ عن وقت برنامج ++C لدي...
هل هناك تفسير محدد يمكن أن ينورنا به أحد الأخوة ؟
تحياتي ...
تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 7 يونيو 2009 في 20:47
اقتباسربما لأن جهازي 64bit
لا أعتقد أن لهذا الأمر علاقة ؟
الأرقام التي يقوم كلا البرنامجين بحسابها تقع تحت 32bit و ليس هناك ميزة من تشغيل البرنامج على معالج 64bit!
تحياتي ..
أنا أحاول ايجاد تفسير ليس الا, ربما الWindows نفسها أسرع لأن الجهاز 64bit
المهم دون الخوض في أمور جانبية هو أننا أثبتنا هنا أن الفروق ضئيلة للغاية بين ++C و #C في هذا البرنامج الذي كان يعتمد اعتماد أساسي على الخوارزمية المستخدمة أكثر من اللغة المستخدمة, و هي حقيقة تظهر كثيراً و لهذا استخدام لغة أسهل و أأمن يعتبر ميزة رائعة بالذات أنك لا تدفع ثمناً كبيراً في سبيل الحصول على هذه المميزات
مصري في بلاد الفرنجة.
قريباً اقرأ مقالاتي على It-scoop
اقتباسأنا أحاول ايجاد تفسير ليس الا, ربما الWindows نفسها أسرع لأن الجهاز 64bit
كما قلت لك لا علاقة لهذا الأمر بالسرعة العجيبة للبرنامج!
اقتباسالمهم دون الخوض في أمور جانبية هو أننا أثبتنا هنا أن الفروق ضئيلة للغاية بين ++C و #C في هذا البرنامج الذي كان يعتمد اعتماد أساسي على الخوارزمية المستخدمة أكثر من اللغة المستخدمة, و هي حقيقة تظهر كثيراً و لهذا استخدام لغة أسهل و أأمن يعتبر ميزة رائعة بالذات أنك لا تدفع ثمناً كبيراً في سبيل الحصول على هذه المميزات
أتمنى أن يعطنا الأخوة بعض النتائج على أجهزتهم هناك شيء غير منطقي في نتيجة برنامج #C لديك!
أنا لم أقل أنك إذا استخدمت خوارزمية سيئة في ++C فإنها أسرع من خوارزمية أفضل من المكتوبة بـ #C!
اذهب إلى Project Euler و ستجد بعض مجانين البرمجة الذين حلو السؤال بثانية واحدة على أجهزة لا تقارن بربع الجهاز الذي لدي و لديك و بلغة مفسرة كبايثون و روبي!
السؤال هو لو كتبت الخوارزمية نفسها باللغتين هل هناك فرق :wink:
و بمناسبة الأمان اكتشف ثغرة في البرنامج الذي قمت بكتابته و سأتعلم #C :P
البرنامج الذي كتبته ليس كل ما يمكن في البرمجة, و لا يهمني اذا كنت تتعلم #C أو لا فهذا اختيار شخصي, أنا شخصياً أجد أن ما تقدمه #C مع ال.net framework يكفيني و زيادة, فعلى الأقل أنا يمكنني كتابة برامج على الويب بنفس اللغة و الأدوات التي استخدمها على الdesktop أو يمكنني كتابة كود يعمل داخل الbrowser باستخدام Silverlight و أيضاً بنفس اللغة
مصري في بلاد الفرنجة.
قريباً اقرأ مقالاتي على It-scoop
وأنا قمت بتجربتها وظهرت لي نفس نتيجة الأخ خالد ...
ولدي تفسير عن سرعة الغريبة بين الأجهزة ... بالنسبة لل++C فهي برنامج يتم تنفيذه مباشرة ... وقد تم بنائه على جهاز 32bit ولن يستفيد من مميزات أجهزة 64bit لأنه تمت ترجمته وبنائه ... لكن بالنسبة لبرنامج ال#C ... فحتى لو تم بنائه على جاهز 32bit ... فهو عبارة عن Managed code وسيتم تفسيره مرة أخرى على جهاز 64bit وتنفيذه ... او ربما يقوم JIT compiler بترجمة البرنامج بناء على مميزات الجاهز وهو 64bit وتحويله إلى كود تنفيذي binary code ....
في النهاية الخوارزمية هي الأساس ... بعدها تأتي أهمية إختيار الData Structures ... وبعدها تأتي أهمية اللغة ...
وهذا موضو كتبته عن أهمية إختيار الData Structures
تم تعديل هذه المشاركة بواسطة b.m.s في 7 يونيو 2009 في 21:50
السلام عليكم ..
اقتباسولدي تفسير عن سرعة الغريبة بين الأجهزة ... بالنسبة لل++C فهي برنامج يتم تنفيذه مباشرة ... وقد تم بنائه على جهاز 32bit ولن يستفيد من مميزات أجهزة 64bit لأنه تمت ترجمته وبنائه
وماذا لو تمت ترجمة البرنامج مثلاً بواسطه مترجم 64 , مثلاً مترجم PGI ??
السلام عليكم ...
شكراً أخي b.m.s على نجدتك لأخوك في الـ ++C :lol:
صراحة أنا غير مقتنع بفكرة الـ 64bit هذه! لماذا تصبح أفضل ؟
لاحظ أنك لو قمت بكتابة شيء في ++C مثل ::
long long x;
و ترجمت الكود ليعمل على معالج 32bit, سوف يضطر المترجم إلى التعامل مع الأعداد الـ 64bit من خلال طبقة إضافة في الـ software أو من خلال استعمال تعليمات المعالج الـ carry add ؟ (لا أعرف x86, هناك addx في معالجات Motorola)
أما الأعداد الموجودة في البرنامج لدينا فهي أصلاً تحت 32bit, و بالتالي ما يحصل هو زيادة المساحة على معالج 64bit دون فائدة حقيقة,
اقتباسوماذا لو تمت ترجمة البرنامج مثلاً بواسطه مترجم 64 , مثلاً مترجم PGI ??
أخي أنا ترجمت البرنامج لـ 386 و تفوق على برنامج #C, ما بالك لو شغلنا شوية Optimizations على شوية خزعبلات!
أستطيع ترجمة البرنامج لمعالجات أكثر حداثة و لكن مالفائدة إذا كان الكود الناتج لـ 386 أسرع من نظيره "المترجم عند التنفيذ لأحدث معالج مدعوم في JIT"!
و بالمناسبة حسب ماقرأت فإنه لايوجد وقت فعلي مستهلك في تشغيل الـ JIT,
إن شاء الله غداً سأقوم بتحميل مترجم GNU و سأبدأ البحث, هذا الموضوع فتح شهيتي من جديد على ++C :lol:
سأترجم الكود لمنصة الأخ متميز و نرى الفرق :P
للأسف النسخة الـ Express لاتدعم الترجمة إلا لـ 32bit :(
ببساطة الفرق من ثلاث إلى أربع أضعاف السرعة تقريباً, حسب التجارب المطروحة, لأن التجارب التي على الأطراف لا تحسب (هكذا تعلمنا في الإحصاء :P )
تحياتي....
تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 7 يونيو 2009 في 22:21
اقتباسيا أخي أنا أيضاً لم أجرب أي خزعبلات هذه نتيجة النسخة الdebug لكن يمكنني مثلاً تطبيق Ngen على البرنامج و هنا يتم ترجمة البرنامج الى Native و هنا ستكون النتيجة رائعة,ولكننا هنا نقارن الأساس
أنا أيضاً شغلت الـ Release لدي, و كان أبطأ بثلاث مرات و أكثر بقليل تقريباً,
لماذا لم تتم عمليات الـ Optimization التي يقوم بها JIT ؟ رغم أنه بإمكانه ترجمة الكود إلى معالج أحدث بكثير من المعالج الذي ترجمت إليه برنامج ++C ؟
هل ترى هناك أمر غير واضح على الأقل...
تحياتي ...
اقتباسيا أخي اقسم بالله العظيم أنا لم افعل سوى أن كتبت البرنامج ثم F5 لم اقم بأي شئ غير هذا.
يا أخي مين جاب سيرتك :lol: ليش آخذ الموضوع بشكل شخصي, صار لي ساعة قاعد أقول انه في شيء في #C مو قادر افهمه :lol:
اقتباسربما نسخة الJIT لل64bit بها تحسينات أكبر
لا أدري صراحة :huh:
طيب سؤال لمن يعرف أي شيء عن معالجات x64 و win x64,
كيف تعمل برامج x86 عليها ؟ هل تتم المحاكاة عن طريق المعالج أم عن طريق طبقة برمجية ؟
هل معالجات x64 تدعم x86 ؟ هل هي متوافقة كما أن جميع المعالجات الحديثة لـ 32bit متوافقة مع ما سبقها ؟ ربما يكون السؤال سخيفاً لأني لا أعرف شيئاً عما يحصل حقيقة :lol:
هناك اشياء اخرى غير المعالج والذاكرة منها سرعة ناقل العناوين واسرعة ناقل البيانات وسرعة الذاكرة نفسها كلها امور ربما تكون غير ملحوظة لكنها تؤدى الى فروق
وشئ اخر هو عدد البرامج التى تعمل على نظام التشغيل فى الوقت الذى يعمل عليه البرنامج ومنها ال cpu usage يعنى congratulations you passed the test :D
مبارك لشعب تونس ![]()
1- x64 اسرع من x86
2- الـOS يستخدم محاكي (WoW64) لتشغيل 32bit apps على x64 .
mov eax, dword ptr ds:[0xffdf0308]
jmp dword ptr [eax+0xfc]
اقتباس- الـOS يستخدم محاكي (WoW64) لتشغيل 32bit apps على x64 .
بالفعل يبدو أن هذا هو السبب!
http://support.microsoft.com/kb/896456
هذا يعني أن المحاكاة تتم في طبقة البرمجيات,
عموماً لامشكلة غداً نترجمه لـ x64 و أجربه في الجامعة :angry:
تصبحون على خير أنا صاحي من أمس :lol:
تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 7 يونيو 2009 في 23:42
المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية
جارٍ التحقق من المتواجدين…