Coder Social home page Coder Social logo

gr-clenabled's Introduction

gr-clenabled - OpenCL-enabled Common Blocks for GNURadio

Gr-clenabled had a number of lofty goals at the project onset. The goal was to go through as many GNURadio blocks as possible that are used in common digital communications processing (ASK, FSK, and PSK), convert them to OpenCL, and provide scalability by allowing each OpenCL-enabled block to be assigned to a user-selectable OpenCL device. This latter scalability feature would allow a system that has 3 graphics cards, or even a combination of GPUs and FPGAs, to have different blocks assigned to run on different cards all within the same flowgraph. This flexibility would also allow lower-end cards to drive less computational blocks and allow FPGAs to handle the more intensive blocks.

The following blocks are implemented in this project:

  1. Basic Building Blocks

    a. Signal Source

    b. Multiply

    c. Add

    d. Subtract

    e. Multiply Constant

    f. Add Constant

    g. Filters (FIR and FFT versions)

    i.	Low Pass
    
    ii.	High Pass
    
    iii.	Band Pass
    
    iv.	Band Reject
    
    v.	Root-Raised Cosine
    
    vi.	General Tap-based
    
  2. Common Math or Complex Data Functions

    a. Complex Conjugate

    b. Multiply Conjugate

    c. Complex to Arg

    d. Complex to Mag Phase

    e. Mag Phase to Complex

    f. Log10

    g. SNR Helper (a custom block performing divide->log10->abs)

    h. [Updated] Forward FFT: This block now supports multiple input/output streams using the same FFT parameters. This allows one GPU to process multiple FFT streams within a single flowgraph. The ability to handle FFT shifts and taps was also added such that this is a true drop-in replacement for the native FFT block.

    i. [Updated] Reverse FFT: Multiple stream support was added here as well. The ability to handle FFT shifts and taps was also added such that this is a true drop-in replacement for the native FFT block.

  3. Digital Signal Processing

    a. Complex to Mag (used for ASK/OOK)

    b. Quadrature Demod (used for FSK)

    c. Costas Loop (2nd order and 4th Order) - Although performance is horrible on a GPU core: ~ 0.7 MSPS.

    d. [New] Polyphase Channelizer (thanks to Dan Banks and Aaron Giles)

    e. [New] Cross-Correlator (time domain and frequency domain, multiple signals) - For the examples included, you'll want gr-xcorrelate (CPU-based cross-correlation with some helper blocks) and gr-lfast for some filter convenience wrappers.

    f. [New] Interferometry X-Engine - This block provides a full X-Engine implementation in GNU Radio based on the industry standard xGPU library. However, it provides dynamic configuration (xGPU requires re-compiling to change parameters), and more flexibility within the parameters. The block can also write correlated data directly to disk for performance, and supports a number of input formats: Packed 4-bit FFT vectors (each byte has 4-bit I and 4-bit Q packed as two's complement), IChar (interleaved byte IQ data) complex FFT vectors, or standard complex FFT vectors.

Supporting Throughput Commandline Tools

There are also a number of performance-measuring command-line tools installed with the module as well:

test-clenabled: Provides throughput timing of the implemented blocks test-clfilter: Provides more granular filter timing test-clfft: Provides specific timing capabilities around FFT throughput. test-clxcorrelate: Provides timing of the reference correlator blocks test-clxengine: Provides timing of the full x-engine block

Important Usage Notes

[New] Reference Cross-Correlators

Time-domain (OpenCL XCorrelate) and frequency-domain (OpenCL XCorrelate FFT) cross-correlator blocks have been added to support combining inputs from multiple antennas.

Time Domain Notes For the time-domain block, parallel queues and other techniques were added to this block to try to get as many parallel operations as possible. However, with the smaller GNURadio block sizes, some other design elements were added to maintain good runtime performance. The block currently takes complex or float inputs (I'm planning on working in IChar shortly too), and acts as a sink block. It will produce output PDUs containing the best correlation score and correlation correction lag. A new CPU-based gr-xcorrelate has a helper block (Extract Delay) that works in tandem with these PDUs that can set variables and control standard delay blocks to align the signals. This helper block also has a "lock" feature that can allow you to dynamically block/allow the delay changes at runtime with a checkbox or other control.

One design element that was incorporated to keep flowgraph performance optimal is two runtime modes: asynchronous or sequential. Since we're acting as a sink block and don't need to output realtime streams of data, async mode can take a block of samples for processing, and pass them to another thread for processing in parallel. The work function can then just return that it processed the samples until the other thread's processing is complete. At which point the worker thread will signal the work function that it should produce the appropriate PDUs on the main thread and pick up the next block. This allows the block to correlate as quickly as possible without holding up processing, and should allow for correlation at any flowgraph sample rate. This also prevents the delay blocks from receiving buffer changes every frame. In sequential mode, the work function will block until processing is completed, which in some scenarios may be the more appropriate approach. Async is the default mode for the block.

Another design element that was included is some user-level tuning using 3 configurable parameters:

  1. Analysis Window - This defines how many samples should be considered for a single correlation calculation. The default is 8192.

  2. Max Index Search Range - This defines how many samples in either shift direction (forward/backward) should be analyzed. For OpenCL, this value should be a power of 2 to allow the max() reduction kernel at the end of the processing chain to function optimally. The default is 512, but this can be adjusted as needed to 256, 1024, 2048, etc. More searches does require extra processing time, so this parameter also serves as one mechanism to regulate processing time. Also, if correlation gets too small at the end of the analysis window, it is expected that incorrect offsets could be returned. So setting this value to say 10-30% of the analysis window minimizes potentially incorrect results.

  3. Keep 1 in N Frames - This mechanism can be used to minimize how frequently new delay updates are generated. For stationary signals, the delays may not change that frequently, so no need to burden down the system and keep producing new varying delay values. By default this value is 4 and applies to both asynchronous and sequential modes (in async mode, the 1-in-N is calculated from when processing completes and is less deterministic. In sequential mode, it is truly a deterministic calcualtion).

Examples: There are a number of examples in the examples directory. Note that you will want to install gr-xcorrelate (up in the ghostop14 github repo) for the extract delay helper function, and gr-lfast for the convenience FFT low pass filter block (this latter block could be dropped from the flowgraph if you do not want to install gr-lfast, just replace it with another filter noting that the FIR filters may lower performance over the FFT version at higher sample rates).

  1. "xcorr test opencl" uses a single data source with a controlled delay to demonstrate correct offset calculations.

  2. "xcorr test opencl 4 signals" uses 4 RTL-SDR inputs (tested with a kerberossdr input) as an FM receiver and correlates all 4 signals for a single output at 2.4 MSPS without any audio jitter.

  3. "xcorr test max rate no ui" drops all of the performance-consuming UI controls, and correlates as an FM receiver at 46 MSPS for audio output without any jitter. This flowgraph does call out some other limitations in that on the test system above 46 MSPS, the FFT low pass filter block starts to become the bottleneck. There is no reason why the cross correlator cannot be run at any sample rate in excess of 60 MSPS in async mode, provided the other blocks in your flowgraph can handle the higher rates as well. Those other blocks will vary in performance based on the CPU of the system they are running on. The FM audio in this example simply served as a good audio feedback mechanism to indicate when the flowgraph was starting to hit performance issues when audio jitter and delay began to be noticable.

Multiple Blocks

Like running an application on your computer that would take 100% CPU utilization, running blocks on a GPU is expecting full hardware utilization for best performance. If you try to run 2 applications on your CPU that both require 100% utilization, performance of both will suffer. The same applies to attempting to run multiple OpenCL blocks on the same hardware at the same time. With that said, these blocks do support using multiple cards simultaneously. You can assign specific blocks to run on specific cards to spread out the load and this will perform quite well. The best recommendation is to take the heaviest processing blocks in your flowgraph that have OpenCL equivalents and start with those.

Hardware Single and Double Precision

Originally some of the blocks like the signal source, quad demod, and the Costas Loop were written with floating point trig functions for hardware compatibility. However it turns out that trig function accuracy is defined as "Implementation Specific" in the OpenCL spec and the precision of the floating point versions were causing discrepancies. As a result the blocks now detect if double precision support is available on the hardware and adjust the code accordingly. The result is actually that the "signal" produced in the signal source with double precision does not have some secondary peaks seen in the native version's frequency plot (see the example flowgraph in the examples directory for the signal source and run it to see the difference). This shouldn't be a problem on newer hardware. You can run the included clview command-line tool which will immediately tell you if your hardware supports double-precision (and most newer cards will). However it is important to check. Single precision trig was poor enough to cause a real-world signal to not decode with the Costas Loop. If you're using custom kernels that include trig functions, keep this in mind. You will want to typecast your sin/cos parameters to (double) or you could get unusable results.

Filters

A lot of work went into the filters. Both FFT and FIR versions are implemented. The test-clfilter command-line tool can help you pick between the 4 filter options: OpenCL FIR, GNURadio's FIR, OpenCL FFT, GNURadio's FFT. Given the number of taps in any one filter and the filter parameters, one of these will be better than the other. In general the order of processing (best to worst) for practical filters will be: GNURadio FFT (by an order of magnitude), OpenCL FIR, GNURadio FIR, OpenCL FFT.

Performance Metrics

A full study on each of the blocks is in the docs directory. It goes through each of the blocks and their measured throughput for a variety of data buffer sizes and compares their performance to the native GNURadio blocks. It was definitely interesting to see the timing on some of the native code as well. The details of how the tests were conducted, the results, and observations are all detailed in the study.

Grouping of Blocks

Once gr-clenabled is installed, there are two high-level groups the blocks are organized into. The first is 'OpenCL-Accelerated'. These blocks always perform better than the CPU equivalents. The other group 'OpenCL-Enabled' has blocks that depending on block size or other parameters may be faster or slower, and some that are just always slower but included here for completeness (like basic multiply/add blocks). For details on how they perform, again look at the performance metrics in the study before choosing.

Building gr-clenabled

In the setup_help directory there are some installation notes for various configurations with details to get set up and any prerequisites.

Included Command-line tools

There are a number of command-line tools that are included with the project that can help with tuning and testing.

clview - clinfo-lite. A quick overview on OpenCL devices with only the information relevant to the blocks. You can grab platform and device ids very quickly from the output of this tool and also determine if your hardware supports double precision math (important for trig functions).

test-clenabled - Provides block timing for each of the modules. You can specify what hardware to run it on and what block size you would like to run it with.

test-clkernel - Used to help test/compile custom kernels and provide timing.

test-clfilter - Provide filter timing information based on a specified number of taps.

Custom Kernel Notes

If you use trig functions in your kernel, verify your hardware supports double precision math. You can do this with clview which will immediately tell you if your card supports it. Then in your kernel, you can still pass floats but make sure you typecast parameters to the trig functions as (double) first or you will notice too much variation in the calculated results.

The following snippit from the project�s /examples/ kernel1to1_sincos.cl example file shows the cast:

c[index].real = cos((double)a[index].real);

If you don't use the double versions (and use clview to ensure your hardware supports it.... most new hardware does but if you have an old card it may be an issue), the trig functions may only be accurate to 9-10 decimal places which during testing was sufficient to cause the Costas Loop to not decode data. It also resulted in about 20 dB of noise showing up in the signal source block until it was switched to double.

gr-clenabled's People

Contributors

ghostop14 avatar radio-dan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gr-clenabled's Issues

Compilation error: cerr is not a member of std

I'm compiling from git and this happens:

[ 26%] Building CXX object lib/CMakeFiles/gnuradio-clenabled.dir/fast_atan2f.cc.o
/home/feanor/Development/gr-clenabled/lib/fft_filter.cc: In member function ‘virtual void gr::clenabled::fft_filter_ccf::compute_sizes(int)’:
/home/feanor/Development/gr-clenabled/lib/fft_filter.cc:79:10: error: ‘cerr’ is not a member of ‘std’
     std::cerr << "fft_filter_ccf: ntaps = " << d_ntaps
          ^~~~
/home/feanor/Development/gr-clenabled/lib/fft_filter.cc:79:10: note: suggested alternative: ‘errc’
     std::cerr << "fft_filter_ccf: ntaps = " << d_ntaps
          ^~~~
          errc
[ 28%] Building CXX object lib/CMakeFiles/gnuradio-clenabled.dir/clFFT_impl.cc.o

Adding #include <iostream> at that offending source code fixes the problem and now the code compiles

missing Frequency Xlating FIR Filter

Hello ghostop14,
thank you for this great project!

Will the missing channelizers, especially the Frequency Xlating FIR Filter, also added to your project?

This would make me very happy. :-)

Compinling fails with CUDA 12

Hey, I want to implement a GNU Radio 250 Msps transceiver and the bottleneck is the filters, so I hope someone can help me get this to work, since this implementation looks quite promising to me.

I think the problem is that I have a newer setup with Ubuntu 22.04 and CUDA-12. CMake runs normally, but with make I get the following error. Could this be related to issue #4 ?

$ cmake ..
-- The CXX compiler identification is GNU 11.4.0
-- The C compiler identification is GNU 11.4.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Build type not specified: defaulting to release.
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.2") 
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE  
-- Checking for module 'gmp'
--   Found gmp, version 6.2.1
-- Found GMP: /usr/lib/x86_64-linux-gnu/libgmpxx.so  
-- Using GMP.
-- Found MPLIB: /usr/lib/x86_64-linux-gnu/libgmpxx.so  
-- Found Boost: /usr/local/lib/cmake/Boost-1.84.0/BoostConfig.cmake (found suitable version "1.84.0", minimum required is "1.84.0") found components: date_time program_options system regex thread unit_test_framework 
-- Found Volk: Volk::volk  
-- User set python executable /usr/bin/python3
-- Found PythonInterp: /usr/bin/python3 (found version "3.10.12") 
-- Found PythonLibs: /usr/lib/x86_64-linux-gnu/libpython3.10.so (found suitable exact version "3.10.12") 
-- Found Git: /usr/bin/git  
-- Extracting version information from git describe...
fatal: No names found, cannot describe anything.
-- Looking for CL_VERSION_2_1
-- Looking for CL_VERSION_2_1 - found
-- Found OpenCL: /usr/lib/x86_64-linux-gnu/libOpenCL.so (found version "2.1") 
STATUS,"Found cl2.hpp"
CMake Warning (dev) at /usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:438 (message):
  The package name passed to `find_package_handle_standard_args` (CLFFT) does
  not match the name of the calling package (clFFT).  This can lead to
  problems in calling code that expects `find_package` result variables
  (e.g., `_FOUND`) to follow a certain pattern.
Call Stack (most recent call first):
  cmake/Modules/FindclFFT.cmake:59 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  CMakeLists.txt:136 (find_package)
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Found CLFFT: /usr/lib/x86_64-linux-gnu/libclFFT.so  
-- Found OpenMP_C: -fopenmp (found version "4.5") 
-- Found OpenMP_CXX: -fopenmp (found version "4.5") 
-- Found OpenMP: TRUE (found version "4.5")  
-- Found Doxygen: /usr/bin/doxygen (found version "1.9.1") found components: doxygen dot 
-- Found PythonLibs: /usr/lib/x86_64-linux-gnu/libpython3.10.so
-- Performing Test HAS_FLTO
-- Performing Test HAS_FLTO - Success
-- Found pybind11: /usr/include (found version "2.9.1")
-- Using install prefix: /usr/local
-- Building for version: gfbfa98d / 1.0.0git
-- PYTHON and GRC components are enabled
-- Python checking for pygccxml - found
-- Configuring done
-- Generating done
-- Build files have been written to: /home/hhi/Software/gr-clenabled/build


$ make 
[  1%] Building CXX object lib/CMakeFiles/gnuradio-clenabled.dir/clMathConst_impl.cc.o
In file included from /home/hhi/Software/gr-clenabled/lib/../include/clenabled/GRCLBase.h:49,
                 from /home/hhi/Software/gr-clenabled/lib/clMathConst_impl.h:25,
                 from /home/hhi/Software/gr-clenabled/lib/clMathConst_impl.cc:26:
/usr/include/CL/cl.hpp:1684:1: error: ‘CL_SEMAPHORE_DEVICE_HANDLE_LIST_KHR’ was not declared in this scope; did you mean ‘CL_DEVICE_HANDLE_LIST_KHR’?
 1684 | CL_HPP_PARAM_NAME_CL_KHR_SEMAPHORE_(CL_HPP_DECLARE_PARAM_TRAITS_)
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.hpp:1684:1: error: template argument 2 is invalid
 1684 | CL_HPP_PARAM_NAME_CL_KHR_SEMAPHORE_(CL_HPP_DECLARE_PARAM_TRAITS_)
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
make[2]: *** [lib/CMakeFiles/gnuradio-clenabled.dir/build.make:76: lib/CMakeFiles/gnuradio-clenabled.dir/clMathConst_impl.cc.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:265: lib/CMakeFiles/gnuradio-clenabled.dir/all] Error 2
make: *** [Makefile:146: all] Error 2

GNC Window Crashes When Changing QT GUI Range

I just installed maint-3.7 using cuda 10.2, and started experimenting with the OpenCL Low Pass Filter.
image
It seems to run fine, except when I have a variable for Beta. When I move the slider, the frequency sink screen crashes. The file input is just a 2 second recording of noise that I had made at one time.
image
The output of GNC when it starts up and is running is as follows:

Generating: '/home/jas/flow/test_opencl_lowpass.py'
Executing: /usr/bin/python2 -u /home/jas/flow/test_opencl_lowpass.py

OpenCL INFO: Filter is using kernel code with faster constant memory.

But when it crashes, I get two additional lines before it gets to Done:

Executing: /usr/bin/python2 -u /home/jas/flow/test_opencl_lowpass.py

OpenCL INFO: Filter is using kernel code with faster constant memory.
OpenCL INFO: Filter is using kernel code with faster constant memory.
OpenCL INFO: Filter is using kernel code with faster constant memory.

>>> Done

Any ideas what might be happening?

Note that this does not happen if I simply select bypass for the OpenCL block.

I'm new to CUDA and openCL, but I want to get better... :)
Thanks.

Compiling Issues

I'm not an expert in OpenCL, so I'm having some issues compiling it on a Ubuntu 16.04:

┌─[lucas@nblucas] - [/media/ELTN/Works/gr-clenabled/build] - [Qui Set 07, 22:25]
└─[$] <git:(master*)> make  
[  1%] Building CXX object lib/CMakeFiles/clview.dir/clview.cc.o
In file included from /usr/local/cuda-8.0/include/CL/opencl.h:42:0,
                 from /usr/local/cuda-8.0/include/CL/cl.hpp:170,
                 from /media/ELTN/Works/gr-clenabled/lib/clview.cc:14:
/usr/local/cuda-8.0/include/CL/cl.h:183:0: warning: "CL_VERSION_1_2" redefined
 #define CL_VERSION_1_2                              1
 ^
/media/ELTN/Works/gr-clenabled/lib/clview.cc:9:0: note: this is the location of the previous definition
 #define CL_VERSION_1_2
 ^
/media/ELTN/Works/gr-clenabled/lib/clview.cc: In function ‘int main(int, char**)’:
/media/ELTN/Works/gr-clenabled/lib/clview.cc:93:14: error: ‘cl_device_svm_capabilities’ was not declared in this scope
              cl_device_svm_capabilities caps;
              ^
/media/ELTN/Works/gr-clenabled/lib/clview.cc:95:49: error: ‘CL_DEVICE_SVM_CAPABILITIES’ was not declared in this scope
              err = clGetDeviceInfo(devices[j](),CL_DEVICE_SVM_CAPABILITIES,
                                                 ^
/media/ELTN/Works/gr-clenabled/lib/clview.cc:96:56: error: ‘caps’ was not declared in this scope
                    sizeof(cl_device_svm_capabilities),&caps,0);
                                                        ^
/media/ELTN/Works/gr-clenabled/lib/clview.cc:98:69: error: ‘CL_DEVICE_SVM_FINE_GRAIN_BUFFER’ was not declared in this scope
              bool hasSVMFineGrained = (err == CL_SUCCESS && (caps & CL_DEVICE_SVM_FINE_GRAIN_BUFFER));
                                                                     ^
lib/CMakeFiles/clview.dir/build.make:62: recipe for target 'lib/CMakeFiles/clview.dir/clview.cc.o' failed
make[2]: *** [lib/CMakeFiles/clview.dir/clview.cc.o] Error 1
CMakeFiles/Makefile2:145: recipe for target 'lib/CMakeFiles/clview.dir/all' failed
make[1]: *** [lib/CMakeFiles/clview.dir/all] Error 2
Makefile:138: recipe for target 'all' failed
make: *** [all] Error 2

using opencl 2 cl2.hpp

Hello,

First, thanks for your job.
I work for many personal project about gnuradio.

I would try to test your blocks but i can't compile them.
I work on ubuntu 16.04 and open library was version 2 with cl2.hpp.

Do you think it is possible to modify your code for use new opencl library ?

Thanks in advance!

complex taps

If the filter tab in the opencl tap-based filter block is complexed, how should we import it?

Discontinuities using Tap-based Filter

I was testing some filters out and noticed that there appear to be some discontinuities using the OpenCL Tap-based Filter. The discontinuity can be seen here:

image

where my flow graph is:

image
OpenCL_Test-FIR.grc.gz

And I am getting an interesting display on the Frequency sink, where at times (as opposed to the first attached pic), it will look like:

image

Does this seem like an issue? Or am I doing something incorrectly?

I'm using the following configurations:

  • Ubuntu: 18.04 LTS
  • gr-clenabled: maint-3.8 (11b091)
  • gnuradio: v3.8.2.0-102-gcc5a816b

Thanks!

PFB Clock Recovery Block

Could you add the PFB Clock Recovery Block from GNU RADIO. It contains a lot of filters which can be paralellized.

GRC: Error in CL FFT block for GNURadio 3.8

Problems in issue #2158 is now existing in GR 3.8. I am observing this in CL-FFT blocks.

Fixes in #1925 is already implemented in GR 3.8. However still the problem exists. Probably some modifications are necessary to this OOT module.

Selection_002

3.10 Mint 21 build problems (boost and iomanip)

I'm trying to build on Mint 21 for gnuradio 3.10, and I'm running into several issues. The first is the need to use updated cl headers, as discussed in the existing issue.

The next issue is with boost. 1.74 is installed, and I get similar issues with undefined references to filesystem classes/operators as what is described in volk issue 242. I propose that we switch to std::filesystem and requires c++17, which if I understood correctly is required for gr 3.10 anyhow.

Lastly, it appears that we need to add a few includes for to resolve some other errors. I don't fully understand why this is necessary when it wasn't before.

I plan to update my fork with what will at least build, but I'm not sure these changes are actually the right answers to the problems so I'm not quite ready to make pull request. Advice/direction is welcome.

FFT size > 4096

Hello,

Whenever I run openCL_Test-FFT.grc with fftsize > 4096, I receive:

:88:21408: error: invalid digit '9' in octal constant
:88:21481: error: invalid digit '9' in octal constant
:88:21602: error: invalid digit 'f' in decimal constant
:88:21690: error: invalid digit 'f' in decimal constant
:88:21778: error: invalid digit 'f' in decimal constant
:88:21866: error: invalid digit 'f' in decimal constant
:88:21954: error: invalid digit 'f' in decimal constant
:88:22042: error: invalid digit 'f' in decimal constant

Any fixing suggestion?

BR, Josh

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.