Setting number of threads and parsing arguments

I understand that to launch Julia with multithreading from command prompt (on Windows), one has to pass the following command before launching Julia: set JULIA_NUM_THREADS=4

I am calling Julia from Excel/VBA using the Shell command. Calling Julia from VBA is simple but I am not sure how to launch it with a specific number of threads and then to execute some Julia code.

A simple example can be something like this:

# VBA code
Sub run()

    code = "C:\Documents\Julia\read.jl"
    file_1 = "C:/Documents/Julia/file1_data.csv"
    file_2 = "C:/Documents/Julia/file2_data.csv"
    file_3 = "C:/Documents/Julia/file3_data.csv"
    var1 = 3.1
    var2 = 2.2
    
Call Shell("cmd /S /K" & "julia" & " " & code & " " & file_1 & & " " & file_2 & " " & file_3 & " " var1 & " " & var2)

End
# file name: read.jl

function read(file1,file2,file3, var1,var2)
        println("File 1 is ",file1)
        println("File 2 is ",file2)
        println("File 3 is ",file£)
       println("Variable 1 is ",var1)
       print("Variable 2 is ",var2)
end

file1 = ARGS[1]
file2 = ARGS[2]
file3 = ARGS[3]
var1 = parse(Float64,ARGS[4])
var2 = parse(Float64,ARGS[5])

read(file1,file2,file3, var1,var2)

May I ask, how to pass the command set JULIA_NUM_THREADS=4 to the above VBA code?

In Julia code, I have about 20 files that are being read (only 3 are shown in the MWE). Do I have to type for each argument …= ARGS[i] for file names and …= parse(Float64,ARGS[i]) for any numerical values (as shown above)? Can this be done using a custom struct or a vector instead? If so, an example of this will be much appreciated.

For recent versions of Julia, you can use the -t flag to specify the number of threads at launch (e.g. julia -t 4).

You can ‘slurp’ and ‘splat’ arguments with ...:

files = [ARGS[1:20]...]
vars = parse.(Int, ARGS[21:end])
read(files..., vars...)

The docs provide more details:

help?> ...
search: ...

  ...


  The "splat" operator, ..., represents a sequence of arguments. ... can be used in
  function definitions, to indicate that the function accepts an arbitrary number of
  arguments. ... can also be used to apply a function to a sequence of arguments.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> add(xs...) = reduce(+, xs)
  add (generic function with 1 method)

  julia> add(1, 2, 3, 4, 5)
  15

  julia> add([1, 2, 3]...)
  6

  julia> add(7, 1:100..., 1000:1100...)
  111107

Thank you.

I need a bit more help here. As I understand, splat arguments are used when the function accepts an arbitrary number of arguments. My function accepts a fixed number of arguments but there are too many arguments.

Is it not better to use struct to define input arguments in that case? Are there any example that explains use of struct instead of using too many variables to define inputs (as in the MWE)?

Packing things into a struct can allow the compiler to perform certain optimizations that are unavailable for Array, but that shouldn’t be too important for a case like this (since your struct elements would include strings, which aren’t isbits and thus can’t be stored inline). A struct is also useful if you want to specialize the behavior or provide custom getters/setters, but it’s not clear to me that your application calls for that. The right choice will depend on what’s happening within read - could you expand on that?

read is reading CSV files and passing the data in format of dataframes to other functions for processing. These csv files contains both numerical data and strings. Other functions are doing numerical computations and data manipulation using DataFrames package. I am not sure if this give you enough to advice.

I do want to specialise the behaviour depending upon the input arguments, e.g., say one of the input arguments var1 accepts either a vector of two dimensions type Float64 or a single Float64 number and then dispatches the right function. I think it requires defining a parametric type but I am still trying to learn how to use it in practice.

It doesn’t necessarily require a parametric type - you can provide runtime dispatch with something like

...
process_var1(var1::Array{Float64, 2}) = ...
process_var1(var1::Float64) = ...
...

function read(files, vars)
   dfs = [DataFrame(CSV.File(file)) for file in files]
   ...
   result1 = process_var1(vars[1])
   ...
end

Thank you