示例#1
0
 public static float[][] DotProduct(DxShader.GpuDevice gpu, float[][] M, bool isCorrelation)
 {
     using (var cc = gpu.CreateConstantBuffer <ShaderConstant>(0))
         using (var sd = gpu.LoadShader("SingleCellAnalysis.DotProduct.cso", Assembly.GetExecutingAssembly())) {
             return(CallShadere(gpu, cc, sd, M, isCorrelation));
         }
 }
示例#2
0
        static void WriteMarix(DxShader.GpuDevice gpu, GBuf buffer, float[][] matrix, int col0, int col1, float[] uploadBuf)
        {
            int rows = matrix.Length;

            Array.Clear(uploadBuf, 0, uploadBuf.Length);
            MT.Loop(col0, col1, col => {
                int offset = (col - col0) * rows;
                for (int row = 0; row < rows; row++)
                {
                    uploadBuf[offset + row] = matrix[row][col];
                }
            });
            gpu.WriteArray(uploadBuf, buffer);
        }
示例#3
0
        static float[][] CallShadere(DxShader.GpuDevice gpu, CBuf cc, ComputeShader sd, float[][] M, bool isCorrelation)
        {
            cc.c.N = M.Length;
            int       columns   = M[0].Length;
            const int groupSize = 256;
            int       distSize  = groupSize * cc.c.N;

            float[][] dMatrix = new float[M.Length][];
            for (int row = 0; row < M.Length; row++)
            {
                dMatrix[row] = new float[row];
            }
            int maxColumns = MaxGpuFloats / cc.c.N;
            int secSize    = Math.Min(columns, (maxColumns > 4096) ? 4096 : (maxColumns - 32));

            float[] uploadBuf = new float[cc.c.N * secSize];

            using (var dataBuf = gpu.CreateBufferRO(cc.c.N * secSize, 4, 0))
                using (var distBuf = gpu.CreateBufferRW(distSize, 4, 0))
                    using (var distStaging = gpu.CreateStagingBuffer(distBuf)) {
                        gpu.SetShader(sd);
                        for (int s0 = 0; s0 < columns; s0 += secSize)
                        {
                            int s1 = Math.Min(s0 + secSize, columns);
                            WriteMarix(gpu, dataBuf, M, s0, s1, uploadBuf);
                            float[] blockDist = new float[distSize];
                            for (cc.c.iBlock = 1; cc.c.iBlock < cc.c.N; cc.c.iBlock += groupSize)
                            {
                                cc.c.columns = s1 - s0;
                                cc.Upload();
                                gpu.Run(groupSize);
                                int iBlock2 = Math.Min(cc.c.iBlock + groupSize, cc.c.N);
                                int bSize   = (iBlock2 - cc.c.iBlock) * (iBlock2 + cc.c.iBlock - 1) / 2;
                                gpu.ReadRange <float>(blockDist, 0, distStaging, distBuf, bSize);

                                int offset = 0;
                                for (int row = cc.c.iBlock; row < iBlock2; row++)
                                {
                                    float[] R = dMatrix[row];
                                    for (int k = 0; k < row; k++)
                                    {
                                        R[k] += blockDist[offset + k];
                                    }
                                    offset += row;
                                }
                                Application.DoEvents();
                            }
                        }
                    }

            if (isCorrelation)
            {
                MT.ForEach(dMatrix, R => {
                    for (int col = 0; col < R.Length; col++)
                    {
                        R[col] = 1.0f - R[col];
                    }
                });
            }
            else     // Euclidean distance is wanted.
            {
                float[] norm2 = new float[M.Length];
                Array.Clear(norm2, 0, M.Length);
                int L = M[0].Length;
                MT.ForEach(M, (R, row) => {
                    float sumSquared = 0.0f;
                    for (int col = 0; col < L; col++)
                    {
                        sumSquared += R[col] * R[col];
                    }
                    norm2[row] = sumSquared;
                });
                MT.Loop(1, M.Length, row => {
                    float[] R = dMatrix[row];
                    for (int col = 0; col < row; col++)
                    {
                        R[col] = (float)Math.Sqrt(Math.Abs(norm2[row] + norm2[col] - 2 * R[col]));
                    }
                });
            }
            return(dMatrix);
        }