سباق تسلح الأنوية في المعالجات المركزية، العبث بعينه!
بعد الكثير من الوقت والتحليل، صارت لدينا حقائق واضحة لا جدال فيها .. لقد أصيبت المعالجات المركزية CPUs المعاصرة بالشلل علي جبهتين: جبهة التردد Frequency، وجبهة أداء النواة الواحدة Single Core .. فهي لا تستطيع الوصول الي تردد عال، وحتي لو وصلت فهي لا تستطيع الاستفادة من هذا التردد العال كما ينبغي من الأساس، وهذا بسبب أن تركيب المعمارية عفي عليه الزمن ويحتاج الي تغيير شمولي يرفع من أداء كل نواة علي حدة.
ولأننا نعيش في عالم تحكمه فلسفة أن الأكثر يعني الأفضل، فلم يتبق أمام مصنعي العتاد سوي سبيل واحد: زيادة عدد أنوية المعالجات المركزية لتصبح أكثر وأكثر! وفي مسعاهم هذا فقد دخل هؤلاء المصنعون في معركة عبثية هدفها تقديم عدد أنوية يفوق ما لدي المٌصنع الآخر، بلا مردود إيجابي حقيقي.
الآن نري معالجات بعشرة أنوية، وبـ 12 وبـ16 بل و بـ 24 و28 و 32 نواة! والآن نستعد للحصول علي 48 و 64! وكل هذا في غضون أعوام قليلة، وكأن الشغل الشاغل لدينا نحن المستخدمين هو أداء الأنوية المتعددة Multi Core! وليس هذا فحسب بل لدينا تقنيات تضيف أنوية وهمية زائدة أو ثانوية علي الأنوية الأصلية، مثل تقنية Hyper Threading من Intel!
وتعريب Thread هو خط او سلسلة، ذلك أن البيانات تذهب الي الأنوية في صورة خط واحد أو سلسلة واحدة لكل نواة، والتقنية تعني حرفيا الخطوط الزائدة Hyper أو السلاسل الزائدة، فهي تجعل لكل نواة خطين أو سلسلتين، خط أصلي وأخر زائد ثانوي، يوضع في خانة الاحتياط ويتم استخدامه في حالة تعطل الخط الأصلي عن العمل لأي سبب، وبهذا تظل النواة مشغولة بالبيانات طوال الوقت، حتي في حالة أعطال تدفق البيانات data bubbles.
لذا نجد أن المعالج ذو الـ 64 نواة هو في الواقع يحوي 128 خطا للبيانات! وهو عدد جنوني بالطبع! حظا سعيدا في استخدامهم كلهم لأداء شئ مفيد!
لقد أهمل مصنعو المعالجات أداء النواة الواحدة، تركوه وسط التراب مدفونا، واتجهوا لزيادات وهمية في عدد الأنوية لا داعي لها، ولا يستفيد منها أحد، ربما سوي تطبيقات الحواسيب الخارقة Super Computers ومصممي الرسوم والعروض ثلاثية الأبعاد! أما نحن المتسخدمين العاديين فلا ناقة لنا في كل هذا ولا جمل!
كل هذه الأنوية لن تساهم في تسريع نظام التشغيل، أو تطبيقات المكتب وتصفح الشبكة الدولية، ولن تساهم في سرعة النسخ والضغط بطريقة الكبيرة، بل ولن تساهم حتي في الألعاب المعقدة!
الألعاب ثلاثية الأبعاد، التي طالما اعتبرها المستهلكون مقياسا حقيقا لقوة العتاد بشكل عام، تعاني من أزمة عنيفة في استغلال تعدد الأنوية، وأول هذه الأزمات هو خلو الألعاب من البيانات التي يمكن تقسيمها وتوزيعها علي كل هذه الأنوية! فاللعبة نفسها لا تحوي كما كبيرا من البيانات المطلوب معالجتها حتي يمكنها توزيعها علي كل هذا العدد من الأنوية!
لعبة ِAshes Of Singularity واحدة من أفضل الألعاب المصممة لتعدد الأنوية، لا تستطيع استهلاك كل الخطوط Threads في معالج Xeon ذو الـ 12 نواة! واستهلاك أول نواة 100% بينما استهلاك باقي الأنوية لا يتعدي 20%، والعديد منهم يظلون بلا عمل!
عادة ما تحوي اللعبة بيانات رسم Rendering، وبيانات محاكاة للطبيعة Physics، وبيانات ذكاء اصطناعي AI وبيانات صوت Sound وتواصل شبكي Networking .. وفقط! في السابق كان كل هذا يعمل علي نواة واحدة فقط Single Core، لأن هذا يوفر علي مطور اللعبة وقتا ومجهودا، فهو يسوق بيانات اللعبة كلها في سلسلة واحدة طويلة Single Thread كالماشية الي نواة المعالج ويتركها هناك ولا شأن له بأي شئ آخر!
لكن مع صعود الأنوية المتعددة Multi Cores، وأٌفول قوة النواة الواحدة، اضطر المطور الي أن يمسك العصا بنفسه، ويتولي تقسيم البيانات في سلاسل مختلفة Multi Threads، كل سلسلة علي نواة مختلفة، وهي عملية مكلفة في الوقت والمجهود. كما أنها شاقة للغاية، لارتباط كل هذه البيانات ببعضها واعتمادها علي بعضها البعض، بيانات المحاكاة تعتمد علي بيانات الرسم والعكس صحيح! فالمعالج لن يرسم اللعبة من دون محاكاة، والمحاكاة لن تتم من دون رسم .. لذا ففصلهما عن بعضهما علي أنوية مختلفة سيؤدي الي انهيار اللعبة كلها.
وكان الحل لهذا هو تقسيم البيانات غير المرتبطة أولا، لذا كان من المعتاد تحميل بيانات الرسم والمحاكاة علي نواة واحدة، والذكاء الاصطناعي علي نواة أخري، والصوت والشبكة علي نواة ثالثة! لذا وبفرض معالج بأربعة أنوية فان استخدام الأنوية لن يتعدي الثلاثة! وهي نسبة ليست بالسيئة! 75% ليست سيئة بالقطع!
لكنها تظل سيئة، لأن البيانات المقسمة غير متناسبة في الكم والتعقيد، فالنواة التي تتولي الرسوم والمحاكاة تكون مشغولة بنسبة 100% بسبب كم البيانات الرهيب الذي تتطلبه عملية الرسم والمحاكاة، بينما تقعد الأنوية الأخري في نعيم، فلا الذكاء الاصطناعي يتطلب بيانات كثيرة، ولا معالجة الصوت ولا الشبكة. وهنا يلاحظ المستخدم أن معالجه يحوي نواة واحدة يتم طحنها بنسبة 100% بينما لا يزيد استهلاك الأنوية الأخري عن 5% أو 10%! ويكون استهلاك المعالج ككل لا يتعدي الـ35%! وهو الأمر الذي نلاحظه جميعا في ألعاب كثيرة لا حصر لها، ونقول حينها ان هذه الألعاب محكومة بأداء نواة واحدة Single Core games، وهي تلك النواة المسكينة المغلوب علي أمرها، رغم أن اللعبة فعليا تستخدم أنوية متعددة، لكن ليس بقدر متساو! وفي تلك الحالة فان سرعة اللعبة تتحدد بسرعة تلك النواة المسكينة، مهما احتوي هذا المعالج علي عدد لا نهائي من الأنوية!
وهنا يجب علينا جميعا تأمل سخرية الموقف، فالمعالج متعدد الأنوية، واللعبة متعددة البيانات، و المطور جعلها متعددة السلاسل Multi Threaded، ومع ذلك ظلت اللعبة محكومة بنواة واحدة، وكأننا لم نفعل شيئا!
نواة واحدة فقط تستهلك بنسبة 100% بينما باقي الأنوية شبه شاغرة ..
بالأعلي نري كيف أن أنوية المعالج يتم طحنها بطريقة غير متماثلة، الي درجة أن ثلاثة أنوية بلا عمل، بينما نواة واحدة مشغولة بالكامل الي حد أن الحمل يفوق طاقتها
وللخروج من هذا المأزق، نعود للمطور من جديد، ونطلب منه تقسيم اللعبة أكثر وأكثر، وهي مهمة شاقة أكثر وأصعب! فيجب الآن علي المطور فصل البيانات المترابطة، يجب عليه بالأساس فصل الرسم Rendering عن المحاكاة Physics رغم اعتمادهما علي بعضهما! وهنا يجب علي المطور أن يصمم لعبته من البداية بحيث لا يعتمد أي من الطرفين علي الآخر بشكل وثيق، يجب أن يسمح تصميم اللعبة بفصل الطرفين من دون مشكلات! وهو أمر ليس بالسهولة التي نتصورها، فهو يتطلب نسف محرك اللعبة نفسه واعادة بناؤه من جديد!
ولقد استغرق هذا الأمر وقتا طويلا في معظم الألعاب والمحركات، لكنه في النهاية أصبح واقعا .. لكن الصورة ظلت غير وردية رغم ذلك!
الآن اللعبة تقسم الرسم علي نواة و المحاكاة علي نواة أخري والذكاء الاصطناعي علي نواة جديدة والشبكة والصوت علي نواة أخيرة، أي ان اللعبة تستغل 4 أنوية بالفعل! لكن يظل الاستهلاك غير متساو علي كل الأنوية، فستجد نواتي الرسم والمحاكاة مشغولتين، بينما تظل النواتين الأخرتين شبه شاغرتين! وهنا يلاحظ المستخدم هذا في هيئة استهلاك 100% لنواتين من معالجه الرباعي، واستهلاك 10% للنواتين الأخريين، أي ان الاستهلاك الكلي للمعالج لم يتعد 60%. وهذا علي معالج رباعي! فما بالك بأخر ذو 6 أو 8 أنوية! ما بالك بـ16 نواة؟! كل هذا العدد الزائد سيكون عاطلا بلا عمل!
لقد انتقلنا من ألعاب محكومة بنواة واحدة الي ألعاب محكومة بنواتين! وكل هذا باستخدام أنوية متعددة!
الاختلاف ما بين 6 أنوية وما هو أكثر في الأداء قليل للغاية .. حتي الاختلاف ما بين 4 و 6 أنوية أقل من الاختلاف ما بين 2 و4 ..
وللخروج من هذا المأزق، فان المطور يقع عليه عبأ تقسيم البيانات الخاصة بالرسم مثلا أكثر، وهو الأمر الذي يعد مستحيلا لاعتماد البيانات الخاصة بتلك المهمة علي بعضها البعض بشكل لا يسمح بفصلها حقا! ونفس الشئ في بيانات المحاكاة! بعض المطورين يحاول بجد في هذا الشأن، لكن نجاح محاولاتهم لا يزال غير مبهر.
لقد ظهر أول معالج رباعي النواة علي الحاسب الشخصي في عام 2006، كان معالج Core 2 Quad من Intel، ولم نشهد ألعابا تستهلك أربع أنوية بشكل كافي ربما سوي عام 2016، أي أن الأمر استغرق 10 أعوام كاملة! ولتخيل الوقت الذي قد نحتاجه لاستهلاك ثمانية أنوية، أو 12 أو حتي 16 فان مجرد التفكير في ذلك يثير الاحباط واليأس!
وبالرغم من توفر المعالجات الرباعية لفترة طويلة عند الجميع، مع ذلك لم يستطع المطورين شغلها بالكامل الا مؤخرا. إن المشكلة ليست في دعم المطورين، المشكلة الحقيقية أن البيانات نفسها لها قابلية محدودة للتشعب.
إن التطبيقات التي تستفيد من تشعب الخطوط Threads قليلة للغاية، مقابل التطبيقات التي لا يمكنها التشعب بشكل كبير، وهؤلاء هم الغالبية العظمي، وهم الذين يؤثرون علي المستخدم بشكل مباشر. إن أغلب تطبيقات مكتبة Adobe علي سبيل المثال (كالـ PhotoShop و Premiere) لا تستطيع الاستفادة حتي الآن من أكثر من 10 أنوية بشكل فعال! وحتي في الحالات التي تستفيد فيها، فان الفارق ما بين 8 أنوية و18 نواة لا يتعدي الـ 25%! وقس علي هذا مئات التطبيقات المشابهة لـ Adobe. البعض يظن أنها مشكلة كسل المطورين في تطوير تلك التطبيقات! بالطبع لا! هي مشكلة تشعب بيانات بالأساس، بعض البيانات لا يمكنها التشعب بعد حد معين مهما فعلت.
تقول Intel أن الحل في هذا هو زيادة تعقيد الألعاب، بحيث يصبح لدي الألعاب بيانات كثيرة أخري يمكن تقسيمها، وهو اعتراف من الشركة بوصولنا لحائط مسدود. تقترح الشركة زيادة تقعيد الرسوم باستخدام اضاءة شمولية Global Illumination، وزيادة تعقيد المحاكاة الطبيعية Physics، عن طريق زيادة التحريك Animation في اللعبة، وزيادة التحطيم Destruction، وزيادة مؤثرات الطقس والرياح والجسيمات Particles، وتقترح أيضا زيادة تحريك الملابس بل وزيادة مسافة رسم الأجسام في الألعاب! وكل هذا في محاولة لايجاد بيانات جديدة تستغل الأنوية المتاحة! بل إن Intel اقترحت زيادة تعقيد بعض المؤثرات في حالة وجود أنوية كثيرة، مثلا زيادة قوة الانفجارات وتفاصيلها اذا كان لدي المستخدم أكثر من 6 أنوية!
والملاحظ هنا أننا نتجنب حل المشكلة الأصلية، فبدلا من أن ننجح في تقسيم بيانات اللعبة الحالية بشكل جيد علي كل الأنوية، فاننا نختلق بيانات جديدة لنضيفها الي تلك الأنوية الشاغرة!
وهو مسعي لا يعد سيئا بالضرورة، فمع مرور الوقت فان تعقيد الألعاب يزداد، لكن المشكلة تكمن في أن التعقيد قد يصل الي مراحل لا يمكن لأجزاء الحاسوب الأخري التعامل معه! قد يزداد معدل التحطيم مثلا والجسيمات الي درجة لا تستطيع بطاقة الرسوم Graphics Card التعامل معها! أو لا تستطيع الذاكرة التعامل معها!
وتلك هي المشكلة الأخري، لا توجد سعة تبادل كافية bandwidth بين الذاكرة والمعالج لتسمح بتبادل بكل هذا القدر من البيانات .. فسرعة الذاكرة تتطور ببطء شديد، وهي لا تكفي مثلا حاليا لتغذية 32 نواة بـ 32 سلسلة بيانات Threads معقدة! فما بالك بـ64 سلسلة؟! أو ما هو أكثر؟!
ثم أن عدد الأنوية الكثيرة هذا يسبب نقاط اختناق متعددة في الذاكرة نفسها، نتيجة أن سرعة استجابة الذاكرة memory latency ليست بالقدر المطلوب، فالذاكرة في الأساس هي وحدة واحدة تتسلم طلبات بيانات من العشرات من الأنوية، ولا تستطيع الاستجابة لكل هذه الطلبات في وقت قصير! والحل الأمثل لهذا هو تخصيص مصفوفة ذواكر لكل نواة مع سلاسلها Thread، وهو الأمر المكلف للغاية مع ازدياد عدد الأنوية والسلاسل. لهذا تجد بعض الألعاب تعمل بصورة أسوأ مع تقنيات زيادة عدد السلاسل مثل Hyper Threading أو Simultaneous Multi Threading. يحتال أصحاب الخوادم Servers علي هذه العقبة باستعمال ذواكر بقنوات تبادل كثيرة memory channels، مثلا 12 قناة، أو باستعمال أكثر من معالج Multi CPU علي اللوحة الأم، ولكل معالج مجموعة ذواكر مخصصة له.
قنوات الاتصال ما بين الذاكرة والمعالج memory channels، نحتاج الي أضعاف هذا العدد مع كل زيادة كبيرة في عدد الأنوية
وفوق كل هذا فان العدد الكثير يسبب نقاط اختناق وتأخير في أدوات التحكم، مثل الفأرة ولوحة المفاتيح، لأن مزامنة معالجة البيانات علي أنوية عديدة مع تلقي أوامر اللاعب في نفس الوقت هو أمر تزداد صعوبته مع ازدياد عدد الأنوية .. وكلما ازدادت صعوبة تلك المزامنة، كلما زاد زمن المعالجة ككل، وتأخرت اللعبة في الاستجابة لأوامر اللاعب!
وليست مشكلات نقاط اختناق الذاكرة وسعة التبادل و تأخير الاستجابة حصرية للألعاب فقط، وانما تمتد أيضا للتطبيقات الأخري كالحوسبة العلمية وتطبيقات الخوادم.
وعلي عكس الشائع بأن تلك التطبيقات تستغل كل الأنوية حتي آخر قطرة، فان الواقع أن هذه التطبيقات عادة ما تستخدم أجزاء معينة من المعالج أكثر من أجزاء أخري، مثلا عادة ما تستعمل تطبيقات الحوسبة العلمية مسرعات الوسائط المتعددة في المعالج (مثل AVX-512) بالأساس، تاركة باقي أجزاء المعالج شاغرة! لكن المشكلة تكمن في أن تركيبة المعالج تمنع أن تعمل هذه المسرعات بتردد عال، وهنا تجد المعالج يعمل بنصف تردده الأصلي مع استخدام هذه المسرعات، والسبب: أداء النواة الواحدة غير جيد مع هذه المسرعات بسبب استهلاكها الشره للطاقة وخرجها الحراري العال مما يحتم قصم التردد الي النصف! وعلي تقنيات التصنيع والمعمارية الحالية فإن إستخدام تلك المسرعات يحرم المعالج من تشغيل باقي أجزاؤه كما ينبغي. وهو نفس السبب الذي يستدعي خفض ترددات المعالج الي الربع في حالة استهلاك كل أنويته في وقت واحد.
باختصار هناك مشكلة مخيفة متكونة في قلب كل معالج، وملخصها أن المعالج لا يمكن تشغيله بنسبة 100% أبدا بحيث تعمل كل أجزاؤه معا في وقت واحد بأقصي قدرة! لابد للمعالج من أن يقلل تردده أو أن يغلق المعالجة في بعض أجزاؤه .. وتسمي هذه الظاهرة باسم الأجزاء المظلمة Dark Silicon، وهي تعيب كل تصميمات المعالجات الحالية، وتمنع وصولهم الي آفاق عليا من الأداء، ومن المفترض أن مصنعي المعالجات يعكفون علي إيجاد حل لهذه الظاهرة المخيفة!
لكن الأسوأ من هذا كله حقا، أن طيش ولهفة مصنعي المعالجات في زيادة عدد الأنوية منعهم من رؤية حماقة السبل التي يستعملونها لزيادتها! فبسبب صعوبات التصنيع واستهلاك الطاقة، فان Intel و AMD قد توقفوا عن تصميم المعالج ككتلة واحدة بأنوية كثيرة في قلبه، واتجهوا الي لصق معالجات صغيرة معا لتكون معالجا كبيرا وهميا!
والفارق بين الطريقتين أن المعالج الأصلي الكبير يحوي وصلات داخلية دائرية Ring Bus، تدور في أرجاء المعالج كله وتوصل الأنوية ببعضها بأقل معدل تأخير ممكن، بينما لا يحوي المعالج الكبير ذو الأنوية الملصوقة هذا، وبدلا من ذلك يستعمل شبكة تواصل mesh كبيرة ذات أجزاء عديدة، تزيد من أزمنة التأخير بشدة، خاصة عندما تحتاج الأنوية الي التواصل فيما بينها. لذا يكون أداء المعالج الملصوق هذا أقل من المعالج الأصلي الكبير! ويكفي أن تعلم أن 50% من استهلاك طاقة المعالج الملصوق يضيع في تشغيل شبكة التواصل بين أنويته!
التواصل ما بين الأنوية الملصوقة مقعد للغاية ومتشعب ..
فضلا عن ذلك فان كل تلك المعالجات كثيرة الأنوية تأتي بترددات منخفضة لتقلل الحرارة واستهلاك الطاقة، تلك الترددات المنخفضة تجعل أداءها أقل في البيانات أحادية الخط Single Thread من المعالجات قليلة الأنوية وعالية التردد .. وهو عيب يجعل المعالجات كثيرة الأنوية غير مناسبة للألعاب مثلا مقارنة بالمعالجات قليلة الأنوية. فتجد معالج مثل i7 8700K ذو الستة أنوية، أفضل من i7 7990X ذو الـ 18 نواة في تشغيل الألعاب!
لا تخدعكم اختبارات المعالجات المركزية الشهيرة مثل Blender و Cinebench وغيرهم، فكلهم يحققون استغلالا مثاليا للأنوية الكثيرة عن طريق استغلالها في الرسم الصريح! بدلا من استغلال المعالج الرسومي في ذلك، والرسم الصريح عملية سهلة التقسيم للغاية، لأنها تتعامل مع الآلاف من نقاط الألوان الغير مترابطة ببعضها وغير معتمدة علي بعضها، والتي يمكن توزيعها علي أنوية منفصلة بلا أي عواقف وخيمة.
إن مصنعي المعالجات أمثال Intel و AMD يعاملون معالجاتهم المركزية CPUs و كأنها معالجات رسومية GPUs، يزيدون في عدد أنويتها بلا اكتراث، غير عابئين أن معمارية X86 ليست مصممة ولا مخصصة للتواصل الشبكي المعقد هذا، فهي لا تملك الأداء ولا كفاءة استهلاك الطاقة التي تملكها المعالجات الرسومية ذات البنيان المتشعب و المتلاحم في ذات الوقت!
بل ان بعضهم وصل بيه التمادي في الامر الي التضحية بما تم إنجازه من دمج وتصغير في العقود السابقة في سبيل الأنوية الكثيرة، لقد فصلت AMD متحكم الذاكرة memory controller ومتحكمات الادخال والاخراج IO controllers خارج المعالج المركزي ووضعتهم في نواة منفصلة جديدة، مصنعة بعملية تصنيع مختلفة، ففي حين يأتي معالج Epyc 2 بـ64 نواة مصنعة علي 7nm، فانه يحوي نواة منفصلة للذاكرة مصنعة بـ 14nm! لتكون النواة الـ 65 في المعالج!
النواة الـ 65 في منتصف معالج Epyc 2 ذو الـ 64 نواة!
إن معاملة أنوية معمارية X86 المعقدة علي أنها مجرد أنوية بسيطة "كأنوية المعالج الرسومي GPU أو كأنوية المصفوفات البدائية FPGA" من شأنه أن يحقق حالة من الفصام ما بين ما يطلبه المستخدمون ويحتاجونه وبين ما يصممه المصنعون من معالجات .. فالمستخدم يطلب معالجا يسرع التطبيقات التي يستعملها حاليا، الآن، او يضيف الي أو يحسن تجربة استخدامه للحاسب، سواء بمزيد من الرسوم أو بمزيد من الخصائص، لكن زيادة الأنوية العبيثة كما نراها الآن لا تحقق هذا ولا ذاك الا في استخدامات ضيقة ومحدودة للغاية، كما أنها تشتت انتباه عالم التقنية عن المشكلة الحقيقية، وهي أن أداء المعالج المركزي قد اصطدم بحائط صد، أو بحجر عثرة يمنعه من التطور كما ينبغي.
إن تحسين أداء النواة الواحدة يسرع كل التطبيقات، ويمكنك من استعمال عدد قليل من الأنوية لانجاز مهام كثيرة وقدر كبير من الأداء، بدلا من أن تضطر الي استعمال عدد أنوية كبير، فتحتاج الي ناقل شبكي يؤخر الأداء بينهم ويستهلك الطاقة في شراهة، وبدلا من أن تحتاج الي ذاكرة مساعدة Cache ضخمة تكفي التواصل ما بين الأنوية، وبدلا من أن تحتاج الي قنوات ذاكرة memory channels كثيرة لتكفي التواصل مع الأنوية كلها، وبدلا من تضع عبأ شنيعا علي المطور لتطويع تطبيقاته وهو الأمر الذي يستغرق الكثير من الأعوام والوقت والمجهود.
نحتاج الي تحسين أداء النواة الواحدة، نحتاج الي رفع التردد ورفع الأداء المستخرج من كل تردد، نحتاج الي معالجات أصغر (لأنها قليلة الأنوية) وأسرع، لا معالجات ضخمة الحجم (لأنها كثيرة الأنوية) متواضعة السرعة وشرهة في استهلاك الطاقة دون عائد يستحق .. نحتاج الي اعادة التركيز علي ما هو أهم، وترك ما هو مجرد عبث ..
إن سباق تسلح الأنوية في المعالجات المركزية، يشبه تماما سباق تسلق الأسلحة النووية أيام الحرب الباردة، أسلحة كثيرة وصواريخ بالألاف صنعت وتُركت تجمع التراب والحشرات في المخازن العسكرية، وبلا فائدة سوي الرغبة الفارغة في الردع والتفاخر .. في النهاية تم تفكيك الترسانة الضخمة كلها ولم يتبق الا أقل القليل منها، ذلك الذي يفيد حقا ويردع وليس الذي يزيد ويفيض بلا داع.
?xml>