Пытаясь найти большие простые числа с Alea GPU - PullRequest
0 голосов
/ 11 июня 2018

Исключение возникает, когда я пытаюсь найти 100-тысячное простое число с помощью Alea GPU.Алгоритм работает хорошо, если я пытаюсь найти меньшее простое число, например, 10 000-е простое число.

Я использую Alea v3.0.4, драйверы NVIDIA GTX 970, Cuda 9.2.

Я новичок в программировании на GPU.Любая помощь будет принята с благодарностью.

long[] primeNumber = new long[1]; // nth prime number to find
int n = 100000; // find the 100,000th prime number
var worker = Gpu.Default; // GTX 970 CUDA v9.2 drivers
long count = 0;

worker.LongFor(count, n, x =>
{                
    long a = 2;
    while (count < n)
    {
        long b = 2;
        long prime = 1;
        while (b * b <= a)
        {
            if (a % b == 0)
            {
                prime = 0;
                break;
            }
            b++;
        }
        if (prime > 0)
        {
            count++;
        }
        a++;
    }

    primeNumber[0] = (a - 1);
}
);

Вот подробности исключения:

Произошло исключение System.Exception HResult = 0x80131500 Сообщение = [CUDAError] CUDA_ERROR_LAUNCH_FAILED Источник = Alea StackTrace: atAlea.CUDAInterop.cuSafeCall@2939.Invoke (строковое сообщение) по адресу Alea.CUDAInterop.cuSafeCall (результат cudaError_enum) по адресу A.cf5aded17df9f7cc4c132234dda010fa7.Copy@918-22.Inopy () 101.O.h. At.jpg1 streamOpt, Memory src, IntPtr srcOffset, Memory dst, IntPtr dstOffset, FSharpOption 1 lengthOpt)
на Alea.ImplicitMemoryTrackerEntry.cdd2cd00c052408bcdbf03958f14266ca (FSharpFunc 2 c600c458623dca7db199a0e417603dff4, Object cd5116337150ebaa6de788dacd82516fa) at Alea.ImplicitMemoryTrackerEntry.c6a75c171c9cccafb084beba315394985(FSharpFunc 2 c600c458623dca7db199a0e417603dff4, cd5116337150ebaa6de788dacd82516fa объекта) в Alea.ImplicitMemoryTracker.HostReadWriteBarrier (Object экземпляр) в Alea.GlobalImplicitMemoryTracker.HostReadWriteBarrier (Object экземпляр) в A.cf5aded17df9f7cc4c132234dda010fa7.clo @ 2359-624.Invoke (объект arg00) в Microsoft.FSharp.Collections.SeqModule.Iterate [T] (источник FSharpFunc 2 action, IEnumerable 1) в Alea.Kernel.LaunchRaw (lunchParam lp, FSharpOption 1 instanceOpt, FSharpList 1 args)на элеa.Parallel.Device.DeviceFor.For (GPU GPU, Int64 от Inclusive, Int64 до Exclusive, Action 1 op) at Alea.Parallel.GpuExtension.LongFor(Gpu gpu, Int64 fromInclusive, Int64 toExclusive, Action 1 op) в TestingGPU.Program.Execute (Int32 t) в C: \ Users .. \ source \ repos \ TestingGPU \TestingGPU \ Program.cs: строка 148
в TestingGPU.Program.Main (строка [] args)

Рабочий раствор:

static void Main(string[] args)
    {
        var devices = Device.Devices;

        foreach (var device in devices)
        {
            Console.WriteLine(device.ToString());                                
        }

        while (true)
        {
            Console.WriteLine("Enter a number to check if it is a prime number:");

            string line = Console.ReadLine();
            long checkIfPrime = Convert.ToInt64(line);

            Stopwatch sw = new Stopwatch();
            sw.Start();
            bool GPUisPrime = GPUIsItPrime(checkIfPrime+1);
            sw.Stop();

            Stopwatch sw2 = new Stopwatch();
            sw2.Start();
            bool CPUisPrime = CPUIsItPrime(checkIfPrime+1);
            sw2.Stop();

            Console.WriteLine($"GPU: is {checkIfPrime} prime? {GPUisPrime} Time Elapsed: {sw.ElapsedMilliseconds.ToString()}");
            Console.WriteLine($"CPU: is {checkIfPrime} prime? {CPUisPrime} Time Elapsed: {sw2.ElapsedMilliseconds.ToString()}");
        }            
    }        

    [GpuManaged]
    private static bool GPUIsItPrime(long n)
    {
        //Sieve of Eratosthenes Algorithm
        bool[] isComposite = new bool[n];
        var worker = Gpu.Default; 
        worker.LongFor(2, n, i =>
        {
            if (!(isComposite[i]))
            {
                for (long j = 2; (j * i) < isComposite.Length; j++)
                {
                    isComposite[j * i] = true;
                }
            }
        });
        return !isComposite[n-1];
    }

    private static bool CPUIsItPrime(long n)
    {
        //Sieve of Eratosthenes Algorithm
        bool[] isComposite = new bool[n];

        for (int i = 2; i < n; i++)
        {
            if (!isComposite[i])
            {
                for (long j = 2; (j * i) < n; j++)
                {
                    isComposite[j * i] = true;
                }
            }
        }

        return !isComposite[n-1];
    }

1 Ответ

0 голосов
/ 13 июня 2018

Ваш код не выглядит правильно.Учитывая параллельный метод for-loop здесь (LongFor), Alea будет порождать «n» потоков с индексом «x», используемым для определения номера потока.Так, например, простой пример, такой как For (0, n, x => a [x] = x);использует «x» для инициализации [] с {0, 1, 2, ...., n - 1}.Но ваш код ядра нигде в коде не использует «x».Следовательно, вы запускаете один и тот же код "n" раз, абсолютно без разницы.Зачем тогда работать на GPU?Я думаю, что вы хотите сделать, это вычислить в потоке "x", является ли "x" простым.Получив результат, установите bool prime [x] = true или false.Затем, после всего этого, в ядре после всего этого добавьте вызов синхронизации, а затем выполните тест с использованием одного потока (например, x == 0), чтобы пройти через prime [] и выбрать наибольшее простое число из массива.В противном случае, существует много коллизий для 'primeNumber [0] = (a - 1);'по-нить на графическом процессоре.Я не могу представить, как вы могли бы получить правильный результат.Наконец, вы, вероятно, захотите убедиться, что с помощью какого-то вызова Alea Prime [] никогда не копируется в / из GPU.Но я не знаю, как ты это делаешь в Alea.Компилятор может быть достаточно умен, чтобы знать, что prime [] используется только в коде ядра.

...