Marko Grdinić
Marko Grdinić

Reputation: 4062

Are the any options for interfacing with the command prompt process from a .NET application other than the standard IO?

Yesterday I figured out that one can control the command line process by redirecting the standard input and writing to it, but now I have a problem that unlike when launching a process directly, if I call the Nvidia NVCC compiler via the command prompt, I do not get any direct reply whether the compilation was successful.

Rather, the F# app I am controlling the command prompt from only sees text and I won't even get a reply for when compilation is done unless I build a parser for the output stream or something to that effect.

The least labor intensive way of getting what I want seems to be using FileSystemWatcher to notify me when the .ptx file is created so I can load it into the program then, but I do not know much about the command prompt, so I thought to ask here whether there are any better solutions than this.

It would be great if I could do something like pass a callback into it instead. Maybe instead of using the standard Ms-Dos prompt, the newer Windows Powershell has some better interfacing features?

Upvotes: 1

Views: 161

Answers (1)

Marko Grdinić
Marko Grdinić

Reputation: 4062

To whom it may be of interest, I decided to go with vitalygolub's idea for my neural net library. Here is how it looks like:

open System
open System.Diagnostics
open System.IO

let compile_kernel_using_nvcc_bat_router kernel_code kernel_name =
    let nvcc_router_path = Path.Combine(kernels_dir,"nvcc_router.bat")
    use p = 
        let procStartInfo = 
            ProcessStartInfo(
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                FileName = nvcc_router_path)

        let outputHandler f (_sender:obj) (args:DataReceivedEventArgs) = f args.Data
        let p = new Process(StartInfo = procStartInfo)
        let print_to_standard_output = outputHandler <| fun x -> printfn "%s" x
        //p.OutputDataReceived.AddHandler(DataReceivedEventHandler (print_to_standard_output))
        p.ErrorDataReceived.AddHandler(DataReceivedEventHandler (print_to_standard_output))
        p

    let quote x = sprintf "\"%s\"" x
    let call x = sprintf "call %s" x
    let quoted_vs_path_to_vcvars = Path.Combine(visual_studio_path, @"VC\bin\x86_amd64\vcvarsx86_amd64.bat") |> quote
    let quoted_vs_path_to_cl = Path.Combine(visual_studio_path, @"VC\bin\x86_amd64") |> quote
    let quoted_cuda_toolkit_path_to_include = Path.Combine(cuda_toolkit_path,"include") |> quote
    let quoted_kernels_dir = kernels_dir |> quote
    let target_path = Path.Combine(kernels_dir,kernel_name+".ptx")
    let quoted_target_path = target_path |> quote
    let input_path = Path.Combine(kernels_dir,"_temp.cu")
    let quoted_input_path = input_path |> quote

    File.WriteAllText(input_path,kernel_code)

    let _ = 
        use nvcc_router_file = File.OpenWrite(nvcc_router_path)
        use nvcc_router_stream = new StreamWriter(nvcc_router_file)

        nvcc_router_stream.WriteLine(call quoted_vs_path_to_vcvars)
        nvcc_router_stream.WriteLine(
            sprintf 
                """nvcc -gencode=arch=compute_30,code=\"sm_30,compute_30\" --use-local-env --cl-version 2015 -ccbin %s  -I%s --keep-dir %s -maxrregcount=0  --machine 64 -ptx -cudart static  -o %s %s"""
                quoted_vs_path_to_cl quoted_cuda_toolkit_path_to_include quoted_kernels_dir quoted_target_path quoted_input_path)

    if p.Start() = false then failwith "NVCC failed to run."
    p.BeginOutputReadLine()
    p.BeginErrorReadLine()
    p.WaitForExit()

    if p.ExitCode <> 0 then failwithf "NVCC failed compilation with code %i" p.ExitCode

    cuda_context.LoadKernelPTX(target_path,kernel_name)

Calling .bat files from a .bat file requires using the call command for legacy reasons. Apart from that it works quite well and terminates with error codes other than zero when compilation fails and outputs the error to the error stream. The input stream handler is commented out on purpose.

Upvotes: 1

Related Questions