0

当我尝试使用 Alea GPU 查找第 100,000 个素数时发生异常。如果我试图找到一个较小的素数,例如第 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 Message=[CUDAError] CUDA_ERROR_LAUNCH_FAILED Source=Alea StackTrace: at Alea.CUDAInterop.cuSafeCall@2939.Invoke(String message) at Alea.CUDAInterop.cuSafeCall(cudaError_enum result) at A.cf5aded17df9f7cc4c132234dda010fa7.Copy@98 -22.Invoke(Unit _arg9)
at Alea.Memory.Copy(FSharpOption 1 streamOpt, Memory src, IntPtr srcOffset, Memory dst, IntPtr dstOffset, FSharpOption1 lengthOpt)
at Alea.ImplicitMemoryTrackerEntry.cdd2cd00c052408bcdbf03958f14266ca(FSharpFunc2 c600c458623dca7db199a0e417603dff4, Object cd5116337150ebaa6de788dacd82516fa) at Alea.ImplicitMemoryTrackerEntry.c6a75c171c9cccafb084beba315394985(FSharpFunc2 c600c458623dca7db199a0e417603dff4, Object cd5116337150ebaa6de788dacd82516fa) at Alea.ImplicitMemoryTracker.HostReadWriteBarrier(Object instance) at Alea.GlobalImplicitMemoryTracker.HostReadWriteBarrier(Object instance) at A.cf5aded17df9f7cc4c132234dda010fa7.clo@2359-624.Invoke(Object arg00) at Microsoft.FSharp.Collections.SeqModule .Iterate[T](FSharpFunc 2 action, IEnumerable1 source) at Alea.Kernel.LaunchRaw(LaunchParam lp, FSharpOption 1 instanceOpt, FSharpList1 args) at Alea.Parallel.Device.DeviceFor.For(Gpu gpu, Int64 fromInclusive, Int64 toExclusive, Action 1 op) at Alea.Parallel.GpuExtension.LongFor(Gpu gpu, Int64 fromInclusive, Int64 toExclusive, Action1 op) at TestingGPU C:\Users..\source\repos\TestingGPU\TestingGPU\Program.cs 中的 .Program.Execute(Int32 t):
TestingGPU.Program.Main(String[] args) 的第 148 行

工作解决方案:

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];
    }
4

1 回答 1

2

您的代码看起来不正确。在这里给定一个并行 for 循环方法 (LongFor),Alea 将产生“n”个线程,索引“x”用于标识线程号是什么。因此,例如一个简单的例子,例如 For(0, n, x => a[x] = x); 使用 "x" 用 { 0, 1, 2, ...., n - 1} 初始化 a[]。但是,您的内核代码不会在代码中的任何地方使用“x”。因此,您运行相同的代码“n”次,完全没有区别。那么为什么要在 GPU 上运行呢?我认为你想要做的是在线程“x”中计算“x”是否是素数。有了结果,设置 bool prime[x] = true 或 false。然后,在内核中,添加一个同步调用,然后使用单个线程(例如,x == 0)进行测试,以通过 prime[] 并从数组中选择最大的素数。否则,'primeNumber[0] = (a - 1);' 会有很多冲突 通过 GPU 上的 n 线程。我无法想象你怎么会得到正确的结果。最后,您可能希望使用一些 Alea 调用确保 prime[] 永远不会复制到 GPU 或从 GPU 复制。但是,我不知道你是如何在 Alea 中做到这一点的。编译器可能足够聪明,知道 prime[] 仅用于内核代码。

于 2018-06-13T13:00:14.947 回答