Здравствуйте, 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++ ничего действительно производительного наваять не может, бо малограмотен и неквалифицирован