На самом деле есть только 2 возможных ответа на этот вопрос:
- Есть еще одна (лучшая) библиотека с высокой точностью, которая работает на CUDA и выполняет то, что вам нужно.
- Вот какизменить эту библиотеку, чтобы она делала то, что вам нужно.
Единственные, кто может дать первый ответ, - это программисты CUDA.К сожалению, если бы была такая библиотека, я уверен, что talonmies знал бы об этом и упомянул об этом.
Что касается # 2, зачем кому-то обновлять эту библиотеку, если они не были программистом CUDA?Существуют и другие, намного лучшие библиотеки мульти-точности.Единственная выгода, которую предлагает CAMPARY - это поддержка CUDA.Это означает, что единственными людьми, у которых есть реальная мотивация работать с библиотекой или изменять ее, являются программисты CUDA.
И, как программист CUDA, наиболее заинтересованный в решении этой проблемы, я нашел решение (хотя иуродливый)Я публикую это здесь в надежде, что эта информация будет полезна для будущих программистов CAMPARY.Для этой библиотеки не так много информации, поэтому это начало.
Первое, что вам нужно понять, - это как CAMPARY хранит свои данные.И хотя это не сложно, это не то, что я ожидал.Исходя из MPIR, я предположил, что CAMPARY хранит свои данные почти таким же образом: показатель степени фиксированного размера, за которым следует произвольное число битов для мантиссы.
Но нет, CAMPARY пошел другим путем.Глядя на код, мы видим:
private:
double data[prec];
Теперь я предположил, что это был просто произвольный способ зарезервировать необходимое им количество бит.Но нет, они действительно используют prec
удваивается.Вот так:
multi_prec<8> a("2633716138033644471646729489243748530829179225072491799768019505671233074369063908765111461703117249");
// Looking at a in the VS debugger:
[0] 2.6337161380336443e+99 const double
[1] 1.8496577979210756e+83 const double
[2] 1.2618399223120249e+67 const double
[3] -3.5978270144026257e+48 const double
[4] -1.1764513205926450e+32 const double
[5] -2479038053160511.0 const double
[6] 0.00000000000000000 const double
[7] 0.00000000000000000 const double
Итак, они сохраняют максимально возможную точность в первом дубле, затем остаток используется для вычисления следующего дубля и так далее, пока они не охватывают все значениеили не хватает точности (отбрасывая младшие значащие биты).Обратите внимание, что некоторые из них являются отрицательными, что означает, что сумма предыдущих значений немного больше, чем фактическое значение, и они корректируют его вниз.
Имея это в виду, мы возвращаемся к вопросу о том, какраспечатайте его.
Теоретически вы можете просто сложить все это вместе, чтобы получить правильный ответ.Но, по определению, мы уже знаем, что в C нет типа данных для хранения значения такого размера.Но другие библиотеки делают (скажем, MPIR).Теперь MPIR не работает на CUDA, но это не нужно.Вы не хотите, чтобы ваш код CUDA распечатывал данные.Это то, что вы должны делать с хостом в любом случае.Поэтому сделайте вычисления с полной мощью CUDA, cudaMemcpy верните результаты, затем используйте MPIR для их распечатки:
#define MPREC 8
void ShowP(const multi_prec<MPREC> value)
{
multi_prec<MPREC> temp(value), temp2;
// from mpir at mpir.org
mpf_t mp, mp2;
mpf_init2(mp, value.getPrec() * 64); // Make sure we reserve enough room
mpf_init(mp2); // Only needs to hold one double.
const double *ptr = value.getData();
mpf_set_d(mp, ptr[0]);
for (int x = 1; x < value.getPrec(); x++)
{
// MPIR doesn't have a mpf_add_d, so we need to load the value into
// an mpf_t.
mpf_set_d(mp2, ptr[x]);
mpf_add(mp, mp, mp2);
}
// Using base 10, write the full precision (0) of mp, to stdout.
mpf_out_str(stdout, 10, 0, mp);
mpf_clears(mp, mp2, NULL);
}
При использовании с числом, сохраненным в multi_prec выше, это выдает точно такое же значение.Yay.
Это не особенно элегантное решение.Необходимость добавить вторую библиотеку только для того, чтобы напечатать значение из первой, явно неоптимальна.И это преобразование не может быть слишком быстрым.Но печать обычно выполняется (намного) реже, чем компьютерная.Если вы потратите на компьютерных часов и несколько отпечатков, производительность не имеет большого значения.И это намного лучше, чем вообще невозможность печатать.
У CAMPARY много недостатков (без поддержки, без поддержки, без поддержки).Но для людей, которым нужны числа mp в CUDA (особенно если вам нужен sqrt), это лучший вариант, который я нашел.