【问题标题】:Trying to find large prime numbers with Alea GPU尝试使用 Alea GPU 查找大素数
【发布时间】:2018-11-20 17:59:08
【问题描述】:

当我尝试使用 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 消息=[CUDAError] CUDA_ERROR_LAUNCH_FAILED Source=Alea StackTrace:在 Alea.CUDAInterop.cuSafeCall@2939.Invoke(字符串消息)在 Alea.CUDAInterop.cuSafeCall(cudaError_enum 结果) 在 A.cf5aded17df9f7cc4c132234dda010fa7.Copy@918-22.Invoke(单位_arg9)
在 Alea.Memory.Copy(FSharpOption1 streamOpt, Memory src, IntPtr srcOffset, Memory dst, IntPtr dstOffset, FSharpOption1 lengthOpt)
在 Alea.ImplicitMemoryTrackerEntry.cdd2cd00c052408bcdbf03958f14266ca(FSharpFunc2 c600c458623dca7db199a0e417603dff4, Object cd5116337150ebaa6de788dacd82516fa) at Alea.ImplicitMemoryTrackerEntry.c6a75c171c9cccafb084beba315394985(FSharpFunc2 c600c458623dca7db199a0e417603dff4,对象 cd5116337150ebaa6de788dacd82516fa) 在 Alea.ImplicitMemoryTracker.HostReadWriteBarrier(对象实例)在 Alea.GlobalImplicitMemoryTracker.HostReadWriteBarrier(对象实例) 在 A.cf5aded17df9f7cc4c132234dda010fa7.clo@2359-624.Invoke(对象 arg00) 在 Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc2 action, IEnumerable1 source) at Alea.Kernel.LaunchRaw(LaunchParam lp, FSharpOption1 instanceOpt, FSharpList1 args)在 Alea.Parallel.Device.DeviceFor.For(Gpu gpu, Int64 fromInclusive, Int64 toExclusive, Action1 op) at Alea.Parallel.GpuExtension.LongFor(Gpu gpu, Int64 fromInclusive, Int64 toExclusive, Action1 op) at 测试GPU.Program.Execute(Int32 t) in C:\Users..\source\repos\TestingGPU\TestingGPU\Program.cs:148 行
在 TestingGPU.Program.Main(String[] 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];
    }

【问题讨论】:

    标签: c# .net cuda gpgpu aleagpu


    【解决方案1】:

    您的代码看起来不正确。在这里给定一个并行 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[] 仅用于内核代码。

    【讨论】:

    • 谢谢!我不知道“n”是产生的线程数。这可以解释为什么我的屏幕会黑屏几秒钟:并行运行的计算太多。我采纳了您的建议并使用 Eratosthenes 算法的筛选来确定 x 是否为素数,并在上面发布了一个可行的解决方案。再次感谢!
    猜你喜欢
    • 2016-07-28
    • 2015-02-28
    • 2019-03-03
    • 1970-01-01
    • 2018-05-21
    • 1970-01-01
    • 1970-01-01
    • 2018-05-20
    • 1970-01-01
    相关资源
    最近更新 更多