Re[8]: Почему математику лучше писать на C++, чем на Java ил
От: drol  
Дата: 23.10.09 22:28
Оценка: 4 (1) +1 -1
Здравствуйте, IID, Вы писали:

IID>А разве непонятно ?


Непонятно. Вы же на скорости настаиваете. Зачем тогда ограничивать участников в возможностях оптимизации ???

IID>Чтобы заставить язык поворочать данными.


Не смешите мои тапки. Поворочать данными — это запроцессить медиаконтейнер в 30Гб, а не елозить по жалкой сотне байт.

IID>Рассчёт по готовой аналитической формуле практически не отличается в разных языках, поэтому и мерять им нечего.


Как интересно. Вроде же ещё недавно Вы кричали что C/C++ быстрее ?

IID>В стандарте языка нет примитивов синхронизации.


Про что и базар. Так ещё раз спрашиваю — причём тут C++ тогда ???

IID>Насколько портабельный ?


У Вас проблемы с чтением ??? Вроде нормальным русским языком написано — "портабельный в рамках стандарта языка". Какие слова Вам непонятны ???

IID>Вариант для MSVC/GCC устроит ? Это легко достигается условной компиляцией.


Устроит код портабельный в пределах стандарта языка Чтобы везде где есть компилятор более-менее соответствующий стандарту работало без каких-либо модификаций. Хоть на DSP всяких, хоть на ARM, хоть на китайских чудо-юдах x86 over MIPS. Только в этом случае можно говорить о программе на языке C/C++.

IID>Если придираться к портабельности — то Mono далеко не полный аналог "некошерной reference-реализации", и при желании можно наклепать код, который не будет "отлично работать".


Не полный аналог, и можно — это правда. Однако предложенный на "турнире" конкретный код, тем не менее, честно — то бишь безо всяких там условных компиляций и им подобных ужасов — переносим.

D>>ОС — часть платформы.


IID>"Платформозависимый код" и "ОС зависимый код" понятия не эквивалентные.


Да, Капитан Очевидность.

IID>И то, что "ОС — часть платформы" этот факт никак не отменяет.


Не отменяет. Это всего лишь определяет "ОС зависимость" как подмножество "платформозависимости".

D>>__sync_val_compare_and_swap


IID>Зависит от ОС.


Неправда. Это зависимость от конкретного компилятора, бо intrinsic. В MSVC++, например, такого intrinsic'а нет. Но есть другой — свой собственной с аналогичной функциональностью.

D>>sched_yield

D>>CPU_ZERO
D>>sched_getaffinity
D>>CPU_ISSET
D>>CPU_SET
D>>pthread_attr_init
D>>pthread_attr_setaffinity_np
D>>pthread_create
D>>pthread_join
D>>pthread_attr_destroy

IID>Тоже самое, зависит от ОС.


Эти — да, ОС.

IID>Собственно все эти вызовы имеют аналоги в Win. Поэтому код портируется тривиально.


Тривиально портируется код на C#. Портирование же предложенного C/C++ кода требует перековыривания ручками почти всего. Если Вы опять желаете поупираться, пожалуйста — портируйте на MSVC++ и покажите diff

D>>Да легко


IID>И где это решение ?


Вы так жаждите его посмотреть ? Пожалуйста:
using System;
using System.Threading;
using System.Text;
using System.Diagnostics;

using size_t = System.Int32;

public class chameneosredux
{
    public enum color_t
    {
        blue,
        red,
        yellow
    }

    private static color_t doCompliment(color_t c1, color_t c2)
    {
        switch (c1)
        {
            case color_t.blue:
                switch (c2)
                {
                    case color_t.blue: return color_t.blue;
                    case color_t.red: return color_t.yellow;
                    case color_t.yellow: return color_t.red;
                    default: break;
                }
                break;
            case color_t.red:
                switch (c2)
                {
                    case color_t.blue: return color_t.yellow;
                    case color_t.red: return color_t.red;
                    case color_t.yellow: return color_t.blue;
                    default: break;
                }
                break;
            case color_t.yellow:
                switch (c2)
                {
                    case color_t.blue: return color_t.red;
                    case color_t.red: return color_t.blue;
                    case color_t.yellow: return color_t.yellow;
                    default: break;
                }
                break;
            default: break;
        }
        throw new Exception();
    }

    private static void printColours()
    {
        printColours(color_t.blue, color_t.blue);
        printColours(color_t.blue, color_t.red);
        printColours(color_t.blue, color_t.yellow);
        printColours(color_t.red, color_t.blue);
        printColours(color_t.red, color_t.red);
        printColours(color_t.red, color_t.yellow);
        printColours(color_t.yellow, color_t.blue);
        printColours(color_t.yellow, color_t.red);
        printColours(color_t.yellow, color_t.yellow);
    }

    private static void printColours(color_t c1, color_t c2)
    {
        Console.WriteLine(c1 + " + " + c2 + " -> " + doCompliment(c1, c2));
    }

    private static String[] NUMBERS = {
      "zero", "one", "two", "three", "four", "five",
      "six", "seven", "eight", "nine"
   };

    private static String getNumber(int n)
    {
        StringBuilder sb = new StringBuilder();
        String nStr = n.ToString();
        for (int i = 0; i < nStr.Length; i++)
        {
            sb.Append(" ");
            sb.Append(NUMBERS[(int)Char.GetNumericValue(nStr[i])]);
        }

        return sb.ToString();
    }

    class meeting_place_t
    {
        public volatile Int32 state;
    }

    class chameneos_t
    {
        public color_t color;
        public size_t meet_count;
        public size_t meet_same_count;
        public volatile bool meeting_completed;
        public meeting_place_t place;
        public chameneos_t[] chameneosAll;
        public int id;
        public bool is_smp;

        public IntPtr affinity;

        const int CHAMENEOS_IDX_MASK = 0xFF;

        [System.Runtime.InteropServices.DllImport("kernel32")]
        static extern int GetCurrentThreadId();

        public void run()
        {
            //struct chameneos_t*         chameneos;
            //struct chameneos_t**        chameneoses;
            //struct chameneos_t*         peer;
            //size_t                      my_id;
            //size_t                      is_same;
            //size_t                      spin_count;
            //uintptr_t volatile*         state_p;
            //uintptr_t                   state;
            //uintptr_t                   peer_idx;
            //uintptr_t                   xchg;
            //uintptr_t                   prev;
            //enum color_t                new_color;
            //int                         is_smp;


            if (IntPtr.Zero != affinity)
            {
                var tid = GetCurrentThreadId();
                foreach (ProcessThread p in Process.GetCurrentProcess().Threads)
                {
                    if (p.Id != tid) { continue; }
                    
                    p.ProcessorAffinity = affinity;
                    break;
                }
            }

            var chameneos = this;
            var chameneoses = chameneos.chameneosAll;

            //state_p = &chameneos->place->state;

            var my_id = chameneos.id;
            var is_smp = chameneos.is_smp;

            var state = chameneos.place.state;
            for (; ; )
            {
                int xchg;
                var peer_idx = state & CHAMENEOS_IDX_MASK;
                if (0 != peer_idx)
                    xchg = state - peer_idx - (1 << MEET_COUNT_SHIFT);
                else if (0 != state)
                    xchg = state | my_id;
                else
                    break;

                var prev = Interlocked.CompareExchange(ref chameneos.place.state, xchg, state);

                //prev = __sync_val_compare_and_swap(state_p, state, xchg);
                if (prev == state)
                {
                    if (0 != peer_idx)
                    {
                        var is_same = (peer_idx == my_id) ? 1 : 0;
                        var peer = chameneoses[peer_idx - 1];
                        var new_color = doCompliment(chameneos.color, peer.color);
                        peer.color = new_color;
                        peer.meet_count += 1;
                        peer.meet_same_count += is_same;
                        peer.meeting_completed = true;
                        chameneos.color = new_color;
                        chameneos.meet_count += 1;
                        chameneos.meet_same_count += is_same;
                    }
                    else
                    {
                        //if (is_smp)
                        //{
                            var spin_count = 20000;
                            while (!chameneos.meeting_completed)
                            {
                                if (0 != spin_count)
                                    spin_count--;
                                else
                                    //sched_yield();
                                    Thread.Sleep(0);
                            }
                        //}
                        //else
                        //{
                        //    while (!chameneos.meeting_completed)
                        //    {
                        //        //sched_yield();
                        //        Thread.Sleep(0);
                        //    }
                        //}
                        chameneos.meeting_completed = false;
                        state = chameneos.place.state;
                    }
                }
                else
                {
                    state = prev;
                }
            }
        }
    }

    class ResultInit
    {
        public chameneos_t[] Creatures { get; set; }
        public Thread[] Threads { get; set; }
    }

    const int MEET_COUNT_SHIFT = 8;
    static ResultInit init_and_start(Int32 meet_count, IntPtr affinity, params color_t[] colours)
    {
        meeting_place_t place = new meeting_place_t();
        place.state = meet_count << MEET_COUNT_SHIFT;
        chameneos_t[] creatures = new chameneos_t[colours.Length];
        for (int i = 0; i < colours.Length; i++)
        {
            Console.Write(" " + colours[i]);
            creatures[i] = new chameneos_t();
            creatures[i].place = place;
            creatures[i].color = colours[i];
            creatures[i].id = i + 1;
            creatures[i].is_smp = false;
            creatures[i].meet_count = 0;
            creatures[i].meet_same_count = 0;
            creatures[i].meeting_completed = false;
            creatures[i].chameneosAll = creatures;
            creatures[i].affinity = affinity;
        }
        Console.WriteLine();

        Thread[] ts = new Thread[creatures.Length];
        for (int i = 0; i < creatures.Length; i++)
        {
            ts[i] = new Thread(creatures[i].run);
            ts[i].Start();
        }

        //if (is_smp)
        //    pthread_attr_setaffinity_np(&chameneos[0][i]->thread_attr,
        //        sizeof(cpu_set_t), affinity);



        return new ResultInit() { Creatures = creatures, Threads = ts };
    }

    static void join_and_output(chameneos_t[] creatures, Thread[] threads)
    {
        foreach (var thread in threads)
        {
            thread.Join();
        }

        int total_meet_count = 0;
        foreach (var cham in creatures)
        {
            total_meet_count += cham.meet_count;
            Console.WriteLine("{0}{1}", cham.meet_count, getNumber(cham.meet_same_count));
        }
        Console.WriteLine(getNumber(total_meet_count));
        Console.WriteLine();
    }

    class ResultHardwareInfo
    {
        public bool IsSMP { get; set; }
    }

    static ResultHardwareInfo GetHardwareInfo()
    {
        var smp = System.Environment.ProcessorCount > 1;
        if (smp)
        {
            //
        }

        return new ResultHardwareInfo() { IsSMP = smp };
    }

    [MTAThread]
    public static void Main(String[] args)
    {
        var sw = new Stopwatch();
        sw.Start();

        Int32 n = 6000000;
        if (args.Length > 0)
            n = Int32.Parse(args[0]);

        printColours();
        Console.WriteLine();

        //    get_affinity(&is_smp, &affinity1, &affinity2);

        bool is_smp = false;

        //if (is_smp)
        //{

        var r1 = init_and_start(n, (IntPtr)(1 + 2), color_t.blue, color_t.red, color_t.yellow);
        var r2 = init_and_start(n, (IntPtr)(4 + 8), color_t.blue, color_t.red, color_t.yellow, color_t.red, color_t.yellow,
          color_t.blue, color_t.red, color_t.yellow, color_t.red, color_t.blue);

        join_and_output(r1.Creatures, r1.Threads);
        join_and_output(r2.Creatures, r2.Threads);

        //}
        //else
        //{

        //var r1 = init_and_start(n, IntPtr.Zero, color_t.blue, color_t.red, color_t.yellow);
        //join_and_output(r1.Creatures, r1.Threads);

        //var r2 = init_and_start(n, IntPtr.Zero, color_t.blue, color_t.red, color_t.yellow, color_t.red, color_t.yellow,
        //  color_t.blue, color_t.red, color_t.yellow, color_t.red, color_t.blue);
        //join_and_output(r2.Creatures, r2.Threads);

        //}

        sw.Stop();
        Console.WriteLine();
        Console.WriteLine("Stopwatch.IsHighResolution = {0}", System.Diagnostics.Stopwatch.IsHighResolution);
        Console.WriteLine("Elapsed {0} milliseconds", sw.ElapsedMilliseconds);
    }
}
Код грубый, со всяким хардкодингом, за корректность зуб не дам и т.д. Желающие могут доточить

D>>Когда чего-то в C/C++ не хватает — Вы сразу разрешаете себе использовать всё что угодно: и intrinsic'и, и сервисы ОС... Однако как только чего-то не хватает в C# — сразу вопли про "подмену понятий"


IID>А чего не хватает в C# ?


"Не хватает" относительно C# я не совсем верно употребил. Это у C++ не хватает А у нас — отсутствует за ненадобностью

IID>Всей реализации хамелеонов целиком ?


Типа того. Когда управляемому коду действительно требуются какие-то специфичные платформозависимые тараканы — берётся interop или C++/CLI. И все счастливы.

IID>Тогда, простите, что останется от C#, если мы будем сравнивать С++ и С++.


То же самое, что остаётся от C++, когда Вы начинаете херачить налево и направо intrinsic'и, да вызовы ОС

IID>Джентльменам верят на слово ?


Конечно Я вот вполне верю цифири опубликованной на сайте "турнира", например. Именно по этой самой причине.

IID>Непонятно, почему до "добавления привязки" (кстати, что за привязка ?)


Установка оптимальной processor affinity mask для нативных потоков исполняющих соответствующие управляемые потоки.

*Так стало яснее ?

IID>выигрыш был всего двукратным ? Напоминаю, перенос опубликованной


У Вас точно затруднения с русским языком В моём постинге написано — "даёт двухкратный рост производительности в сравнении с выполнением опубликованного C# кода". По-моему вполне понятно, что прирост не относительно цифири с сайта, а относительно результатов исполнения кода с сайта у меня.

IID>C# реализации с моно на компилятор C# от MS дал сразу 4-х кратный прирост производительности.


На моей системе прирост получился меньшим чем на Вашей => ~18 секунд исполнялось. Правда у меня куча барахла в background'е постоянно вертится + коммит превышает физическую память в полтора раза

IID>Хочу увидеть C# реализацию, где разрыв уменьшился хотя бы до 5 раз.


Вот мой порт такой и есть, и даже лучше => ~2.7 секунды.

IID>Тогда будет иметь смысл и портабельность сделать.


Условная компиляция — это другая портабельность.

IID>И взять Intel С++ Compiler.


Да не будет в этом никакого смысла. Результат уже давно на лице. Чтобы превзойти чемпионскую программу на Haskell'е, сообществу C/C++ потребовался такой мегагуру нативных concurrency и параллелизма как (много)уважаемый remark. Все же остальные представители "расово верного языка" слили по-полной.

Всё это показывает очевидную закономерность — для C/C++ производительность кода определяется не языком, а прежде всего личностью того, кто этот код пишет. И типичный представитель лагеря C/C++ ничего действительно производительного наваять не может, бо малограмотен и неквалифицирован
Re[7]: Почему математику лучше писать на C++, чем на Java ил
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 24.10.09 23:33
Оценка:
Здравствуйте, drol, Вы писали:

В дальнейшем, пожалуйста, воздержись от личных наездов.
... << RSDN@Home 1.2.0 alpha 4 rev. 1249 on Windows 7 6.1.7600.0>>
AVK Blog
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.