По моему опыту, не имеет смысл использовать shared memory в большинстве задач, потому что просто нечего там хранить: прочитал элемент из global или текстуры, обработал, сохранил туда же или в другой буфер.
Классическим примером, где нужно использование shared, является перемножение матриц, там это дает большое ускорение, но это весьма специфический пример.
В своих задачах я использую shared memory в основном при всякой редукции, тут она нужна чисто для обмена данными между потоками в блоке. Но для этого в той же CUDA есть и другие механизмы, можно обойтись и без нее.
Еще shared memory нужна, когда каждому потоку нужен какой то локальный буфер для своих вычислений. Но здесь размер буфера получается весьма ограничен, да и честно сказать это не очень эффективно. Если в задаче требуется буфер, то обычно ее достаточно сложно реализовать на gpu.
Больше что-то ничего не приходит в голову, для чего может shared memory понадобиться. Скорее в остальном это специфические задачи.
На самом деле задач, где имеет смысл использование shared памяти на gpu не так уж много. Nvidia в свое время сделало кэширование global памяти, такое же как в обычных процессорах, но потом в один прекрасный момент молча это выпилили. В результате производительность в конкретной задаче конкретно просела. В замен они добавили специальную инструкцию, для чтения глобальной памяти, которая гарантировала попадание данных в кэш. Но только это работало для константных данных и следить за тем, чтобы они не менялись должен был сам разработчик.
Речь вроде была о влиянии точности вычислений на сходимость алгоритма построения таблиц. Причем тут вообще ГСЧ? В построении таблиц он никак не участвует.
Речь о realtime сигналах (sig >= SIGRTMIN) путем установки:
fcntl(fd, F_SETSIG, sig)
для дескриптора
и последующем получении информации об I/O событиях через sigwaitinfo()/sigtimedwait()
Здесь как раз отсутствуют проблемы poll()/select() выраженные в квадратичной сложности от количества сокетов. А realtime сигналы избавлены от проблем обычных сигналов.
В свое время (10 лет назад) реализовывал на этом сервер. Все работало без проблем.
Корень проблемы в том, что maxCharsPerByte() возвращает float. Почему так сделано я не знаю, но видимо это не обсуждается. В результате при умножении результата maxCharsPerByte() на int происходит умножение int на float. При арифметической операции с операндами разного типа оба операнда приводятся к тому типу, который может представить больший диапазон чисел, в данном случае это float. Но т.к. у float разрядность мантиссы 24 бита, а у int разрядность 32 бита, при привидении int к float сохраняются только 24 старших значащих бита, а младшие обнуляются, также если результат умножения получается больше 2^24, то его младшие биты тоже теряются. В итоге результат умножения получается меньше, чем должен быть в точной арифметике.
На мой взгляд нормальным исправлением должно бы было быть изменение возвращаемого типа maxCharsPerByte() на целый, но видимо это невозможно по каким то причинам, поэтому приведение к double вполне корректное решение.
Видимо проблема проявляется только под нагрузкой, возможно когда из-за этого процессор повышает тактовую частоту. Я думаю стоит попробовать ограничить или уменьшить максимальную частоту процессора и посмотреть будет ли повторяться проблема.
В любом случае других разумных объяснений, кроме ошибки процессора не вижу.
А другие приложения, использующие floating point, не глючат на этой машине?
Выглядит все как ошибка железа при выполнении команды cvtss2sd.
А можно еще проверить, точно там 0.0 получается. Может cout просто выводит денормализованные значения как 0.
Можно заменить: std::cout << "(double)1.0f = " << resultd << std::endl;
на std::cout << "(double)1.0f = " << *(long long*)&resultd << std::endl;
Конфигурация там достаточно хорошая: Core i7-6800K, 64G памяти, GeForce GTX 1070, но на самом деле в основном решает видеокарта. В библиотеке реализовано 3 способа рендера: программный рендер (на обычном процессоре), на CUDA и на OpenCL. CUDA — наиболее оптимальна. Даже слабенькая видеокарта дает результат лучше, чем самые мощные процессоры. На самом деле картинка и качество будет не сильно отличаться от того, что в видео, даже на бюджетных видеокартах.
Вообще у нас на сайте выложены полнофункциональные версии нашего просмотрщика с триальным периодом в 1 месяц: здесь. Можно попробовать самому повторить все, что описано в статье.
Полигональный рендер на GL. Потом сливаем картинки через буфер глубины.
С VTK примерно та же история, что с ITK — тоже большая и медленная, но это опять же косвенные впечатления — на основе ПО, ее использующего.
Так сложилось, что в свое время была нужна библиотека воксельного рендера для одного проекта. В результате использовали библиотеку volpack. По мере развития проекта библиотеку дописывали, распараллелили и оптимизировали, но в определенный момент пришло понимание, что используемый в ней метод — shear-warp — тупиковый. На основе полученного опыта написали свою библиотеку с нуля уже на основе ray-tracing'а.
У меня сложилось впечатление, что многие вещи в ITK и вообще в открытых библиотеках, реализованы людьми, по образованию являющимися скорее математиками, а не программистами. Это накладывает отпечаток, на код, ими написаный. Например, как мне кажется, если конструкции эквивалентны математически, для математика они выглядят абсолютно эквивалентными и в плане программирования. Так, например, вот здесь автор при реализации level set сегментации, в этом файле для возведения в квадрат использует функцию pow(x, 2.0). Простая замена на x*x дала ускорение всего кода в 2 или 3 раза (уже точно не помню). А вот статьи, описывающие алгоритм, зачастую, в таких случаях написаны весьма качественно. Т.ч. я предпочитаю собственную реализацию, на основе изучения статей.
1. ITK мы не используем. У нас библиотеки собственной разработки для воксельного рендера и для алгоритмов сегментации. Объективно про ITK сказать что-то вряд ли смогу, но субъективные впечатления, на основе того, что о ней знаю такие: библиотека весьма громоздкая и зачастую алгоритмы реализованы весьма неоптимально — по опыту сравнения с ПО, ее использующим, собственная реализация алгоритма часто оказывается в разы быстрее.
2. Применяем стандартный алгорим. Более того есть собственная модификация алгоритма, генерирующая меньшее количество треугольников. Количество треугольников зачастую является одним из основных критериев — задача, ради которой строится сетка, может не тянуть большого количества элементов. Если же в приоритете именно точность сетки, то не вижу преимущества предложенного алгоритма. Он может дать более гладкую сетку, но не более точную — для увеличения точности лучше просто увеличить разрешение модели (уменьшить размер куба). В качестве примера — если в качестве границы принять определенное значение плотности, то при трилинейной интерполяции эта граница может проходить в произвольном месте вокселя. При увеличении разрешения сетка пройдет ближе к такой границе (т.е. абсолютная ошибка уменьшится), предложенный же алгоритм все равно сгенерирует сетку, проходящую через те же места на ребрах куба вокселя, что и стандартный, т.е. ошибка не уменьшится.
3. Да, были попытки использовать градиент в качестве дополнительного измерения передаточной функции. Но честно сказать реальной пользы на практике от этого получить не удалось. Можно конечно поэксперементировать с реально многомерными данными, вроде МРТ в Т1/Т2, но есть сомнения, что удастся получить качественно другую визуализацию.
Добрый день!
Такие мысли приходят наверное ко всем :) Не стоит отчаиваться, главное чтобы было интересно и кому-то нужно. Глядя на количество существующих подходов и методов, понимаешь как мало еще всего сделано. Область большая, возможно каждому удастся сделать что-то свое.
Классическим примером, где нужно использование shared, является перемножение матриц, там это дает большое ускорение, но это весьма специфический пример.
В своих задачах я использую shared memory в основном при всякой редукции, тут она нужна чисто для обмена данными между потоками в блоке. Но для этого в той же CUDA есть и другие механизмы, можно обойтись и без нее.
Еще shared memory нужна, когда каждому потоку нужен какой то локальный буфер для своих вычислений. Но здесь размер буфера получается весьма ограничен, да и честно сказать это не очень эффективно. Если в задаче требуется буфер, то обычно ее достаточно сложно реализовать на gpu.
Больше что-то ничего не приходит в голову, для чего может shared memory понадобиться. Скорее в остальном это специфические задачи.
fcntl(fd, F_SETSIG, sig)
для дескриптора
и последующем получении информации об I/O событиях через sigwaitinfo()/sigtimedwait()
Здесь как раз отсутствуют проблемы poll()/select() выраженные в квадратичной сложности от количества сокетов. А realtime сигналы избавлены от проблем обычных сигналов.
В свое время (10 лет назад) реализовывал на этом сервер. Все работало без проблем.
На мой взгляд нормальным исправлением должно бы было быть изменение возвращаемого типа maxCharsPerByte() на целый, но видимо это невозможно по каким то причинам, поэтому приведение к double вполне корректное решение.
А другие приложения, использующие floating point, не глючат на этой машине?
А можно еще проверить, точно там 0.0 получается. Может cout просто выводит денормализованные значения как 0.
Можно заменить:
std::cout << "(double)1.0f = " << resultd << std::endl;на
std::cout << "(double)1.0f = " << *(long long*)&resultd << std::endl;А можно вывести результат приведения float к double, когда происходит ошибка?
Т.е. вместо:
float result = 1.0;
if (result != 1.0) {
error++;
...
}
Написать что то вроде:
float result = 1.0;
double resultd = result;
if (resultd != 1.0) {
error++;
std::cout << "(double)1.0f = " << resultd << std::endl;
...
}
Вообще у нас на сайте выложены полнофункциональные версии нашего просмотрщика с триальным периодом в 1 месяц: здесь. Можно попробовать самому повторить все, что описано в статье.
С VTK примерно та же история, что с ITK — тоже большая и медленная, но это опять же косвенные впечатления — на основе ПО, ее использующего.
Так сложилось, что в свое время была нужна библиотека воксельного рендера для одного проекта. В результате использовали библиотеку volpack. По мере развития проекта библиотеку дописывали, распараллелили и оптимизировали, но в определенный момент пришло понимание, что используемый в ней метод — shear-warp — тупиковый. На основе полученного опыта написали свою библиотеку с нуля уже на основе ray-tracing'а.
2. Применяем стандартный алгорим. Более того есть собственная модификация алгоритма, генерирующая меньшее количество треугольников. Количество треугольников зачастую является одним из основных критериев — задача, ради которой строится сетка, может не тянуть большого количества элементов. Если же в приоритете именно точность сетки, то не вижу преимущества предложенного алгоритма. Он может дать более гладкую сетку, но не более точную — для увеличения точности лучше просто увеличить разрешение модели (уменьшить размер куба). В качестве примера — если в качестве границы принять определенное значение плотности, то при трилинейной интерполяции эта граница может проходить в произвольном месте вокселя. При увеличении разрешения сетка пройдет ближе к такой границе (т.е. абсолютная ошибка уменьшится), предложенный же алгоритм все равно сгенерирует сетку, проходящую через те же места на ребрах куба вокселя, что и стандартный, т.е. ошибка не уменьшится.
3. Да, были попытки использовать градиент в качестве дополнительного измерения передаточной функции. Но честно сказать реальной пользы на практике от этого получить не удалось. Можно конечно поэксперементировать с реально многомерными данными, вроде МРТ в Т1/Т2, но есть сомнения, что удастся получить качественно другую визуализацию.
Такие мысли приходят наверное ко всем :) Не стоит отчаиваться, главное чтобы было интересно и кому-то нужно. Глядя на количество существующих подходов и методов, понимаешь как мало еще всего сделано. Область большая, возможно каждому удастся сделать что-то свое.