Pull to refresh
25
0
Александр Синотов @BratSinot

User

Send message
Полупроводники с ненадежной оболочкой (к примеру пластмасса) меняют параметры при повышении освещения.

Так помнится есть микроконтроллеры, которые можно стирать ИК излучением.

Поправьте меня, если я где-то ошибся, микроконтроллерами не занимаюсь, поэтому мог наврать.
А ну да, насчет нуля я не подумал, каюсь.
Не знаю как сейчас, но раньше свой QSort работал быстрее qsort'а из stdlib.h. Возможно это из-за дополнительных проверок, или в stdlib.h устойчивая сортировка реализована и т.п.
Насчет x86 / amd64 инструкций слегка ошибся, там какие-то хитры SSE инструкции используются. Но в любом случае, в вашем варианте гораздо больше операций выполняется.
int greater(const void* p, const void* q) // трёхстороннее сравнение
{ 
  double x = *(double*)p; // получить значение double с адреса p 
  double y = *(double*)q; 
  if (x>y) return 1; 
  if (x<y) return -1; 
  return 0; 
} 

Зачем так усложнять?

int greater(const void* p, const void* q) // трёхстороннее сравнение
{ 
  return *(double*)p - *(double*)q; 
} 

Короче, меньше и быстрее (одна инструкция sub и ret, заместо cmp, mov и ret в x86 / amd64).
Так все функции сравнения в C работают (поэтому в описаниях всяких там memcmp() в возвращаемом значении и указано, что либо 0, либо >0, либо <0).

Мне меньше всего нравится qsort() из стандартной ISO библиотеки C:

А вот с этим не согласен. Если не брать в расчет варианты std::sort() где мы работает с объектами (std::pair или какие-нибудь массивы данных разного размера), то в C++ она таже самая. Т.е. мы указываем начало, конец и функцию сравнения (просто в C заместо конца мы указываем длину и размер элемента).

Помнится в свое время, когда в задаче требовалось использовать std::sort(), для меня было очень странным, что в аргументах передается указатель начала массива и указатель его конца.
У Линуса не было цели, вспомните сообщение в рассылке Minix.
Так можно либо подпаяться к нужным проводкам, либо сделать вывод на эти проводки, либо сам контролер «запихать» в разъем.
только программа при этом становится абсолютно нечитаемой

О том и речь. Эмулировать или извращаться можно на любом языке, только это плохо, поэтому в расчет не берется.
Можно заменить другим.

А можно узнать чем можно заменить адресную арифметику? Только без костылей, чтоб было так-же удобно.

100 лет назад, когда писал на фортране, связка ассемблер+фортран+линкер вполне работала.

А каким образом вы линкером вставите ассемблерный код посреди кода на Fortran'е? Что-то вроде этого:
#include <stdio.h>

int main(void) {
	//Меняем переменные местами с помощью инструкции x86 процессора
	int a = 0xAABBCCDD, b = 0xFFFFFFFF;
	__asm__
	(
		"xchgl %[a], %[b]\n\t"
		: [a]"+r"(a), [b]"+r"(b)
	);
	printf("%x\n%x\n", a, b);

	//Меняем байты местами с помощью инструкции циклического сдвига x86 процессора
	short int c = 0xAABB;
	__asm__
	(
		"rorw $8, %[c]\n\t"
		: [c]"+r"(c)
	);
	printf("%hx", c);
}

Примеры, конечно, уровня Hello World, но в вашем случае это можно сделать только путем вызова функции, а это лишние действия по её вызову. Да и когда требуется вызвать одну инструкцию, городить целую функцию это слишком.

Речь же не о написании драйверов.

Речь шла о работе с устройствами, что из той-же оперы.
А что насчет адресной арифметики, ассемблерных вставок, типов (ну в C это модификатор) наподобие volatile?
Да и в C гораздо удобнее работать с бинарными данными, включая IO-операции, ежели в Fortran. Я лично в этом убедился на том маленьком коде в статье.

Если целесообразность использования Fortran в мат. задачах еще можно оправдать, то превосходство в низкоуровневом программировании C сомневаться сложно. Может в Fortran'е и подобные задачи можно решать, но во некоторых моментах придется много «костылей» и «велосипедов» городить.
А кто заставляет переписывать? Вопрос был про новый код. А существующие библиотеки никто не запрещает использовать хоть из Python.

Так так и делают. В том-же Fortran 2003 на уровне спецификации появились способы взаимодействия с C.

Хотя и существующее переписывают «почему-то», например ЦЕРН давно перешел с CERNLIB [Fortran] на ROOT [C++].

Если не ошибаюсь, то у них там было куча legacy кода и проще было начать с нуля, ежели исправлять старое.
Ну так Fortran используют из-за того, что за полвека создано очень много хороших библиотек, ну а переписывать на С это нужно потратить много времени, да и в целом не очень нужно (зачем, коли на Fortran хорошо работает).
Для x87 FPU может быть, ибо у FSQRT latency в среднем 27, но x87 сам по себе тормознутый, т.к. там происходит куча накладных расходов, при работе с его «стековыми регистрами».

С SSE все проще, у sqrtsd latency 7-32, а так-же очень легко можно перегонять значения между XMM, памятью и регистрами процессора.

Я специально замерял, разницы в скорости не было. Время выполнение каждого варианта колебалось от 10 до 12 секунд, при 2048 итерациях и разрешении 8192. Если там и был какой-то прирост, то он съедается планировщиком процессов, IO планировщиком и скоростью записи на HDD.

Проще говоря, в данной ситуации я предпочту использовать CDABS(), т.к. в коде это выглядит элегантнее, а выигрыша никакого нет.
16 потоков было выбрано экспериментально для моей машины, т.к. эмпирическим путем сразу учитывается работа планировщика процессов.

А счетчики в Fortran по умолчанию PRIVATE.
Оу, про iter, z и iter2 я как-то и не подумал. Просто в варианте на C они у меня локальные переменные, следовательно для каждого потока свои. На днях поищу информацию о локальных переменных в Fortran, исправлю.

Кстати говоря, в do цикле x и y автоматически private.
Если сравнить:
REAL(z)**2 + AIMAG(z)**2

и:
CDABS(z)

Разница получится в 1 μops (в моем случае sqrtsd из SSE), на скорость это практически не влияет. По крайней мере на форе IO операций записи на диск это не заметно.

А что до того зачем писать — just for fun. Лично мне нравится ковырять различные языки программирования.
Честно говоря даже не знаю. Но это скорее всего проблема не самого OpenMP (спецификации), а его реализаций, а так-же работы SMT в конкретной OS.
Изначально и было приписано PRIVATE(x, y), только зачем? Я же их только читаю, поэтому можно и не указывать. Ну можно приличия ради, пусть по регистрам процессора раскидает.
А что до верификации… смысл? Тут задача не провести мат. расчеты, а сгенерировать «прикольную» картинку, да и текст учебный, не стоит лишний раз его усложнять.
Ну в конкретно этом случае, при генерации Множества Жюлиа с 2048 итерациями, изображение 4096x4096 с OMP генерировалось 3.175 секунд, а без OMP 5.759 секунд на процессоре Core i3 330M с 2 ядрами и HyperThreading.

А вообще, когда я ковырял OMP и OpenCL на C, то все было как-то так:
639x349

В принципе тут разницы большой между Fortran'ом и C не будет, т.к. код тривиальный, без использования каких-то хитрых возможностей.

Но там я генерировал Мандельброта и использовал float, т.к. у меня небыло видеокарты, которая поддерживает числа двойной точности.
Так, тогда я ничего не понял, у «чего» в этом примере нет имени?

Information

Rating
Does not participate
Location
Кингисепп, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity