$ cd /usr/local/cuda-11.4/samples/4_Finance/BlackScholes
$ sudo make BlackScholes
$ ./BlackScholes
[./BlackScholes] - Starting...
GPU Device 0: "Pascal" with compute capability 6.1
Initializing data...
...allocating CPU memory for options.
...allocating GPU memory for options.
...generating input data in CPU mem.
...copying input data to GPU mem.
Data init done.
Executing Black-Scholes GPU kernel (512 iterations)...
Options count : 8000000
BlackScholesGPU() time : 0.227898 msec
Effective memory bandwidth: 351.033566 GB/s
Gigaoptions per second : 35.103357
BlackScholes, Throughput = 35.1034 GOptions/s, Time = 0.00023 s, Size = 8000000 options, NumDevsUsed = 1, Workgroup = 128
Reading back GPU results...
Checking the results...
...running CPU calculations.
Comparing the results...
L1 norm: 1.741792E-07
Max absolute error: 1.192093E-05
Shutting down...
...releasing GPU memory.
...releasing CPU memory.
Shutdown done.
[BlackScholes] - Test Summary
NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.
Test passed
TensorRT-8.4.3.1/python/ 폴더에서 현재 파이썬 버전에 맞는 패키지 설치
$ pip install tensorrt-8.4.3.1-cp36-none-linux_x86_64.whl
Defaulting to user installation because normal site-packages is not writeable
Processing ./tensorrt-8.4.3.1-cp36-none-linux_x86_64.whl
Installing collected packages: tensorrt
Successfully installed tensorrt-8.4.3.1
TensorRT-8.4.3.1/uff/ 폴더에서도 설치
$ cd ../uff/
$ pip install uff-0.6.9-py2.py3-none-any.whl
Defaulting to user installation because normal site-packages is not writeable
Processing ./uff-0.6.9-py2.py3-none-any.whl
Requirement already satisfied: protobuf>=3.3.0 in /home/ym/.local/lib/python3.6/site-packages (from uff==0.6.9) (3.17.3)
Requirement already satisfied: numpy>=1.11.0 in /home/ym/.local/lib/python3.6/site-packages (from uff==0.6.9) (1.19.5)
Requirement already satisfied: six>=1.9 in /home/ym/.local/lib/python3.6/site-packages (from protobuf>=3.3.0->uff==0.6.9) (1.15.0)
Installing collected packages: uff
Successfully installed uff-0.6.9
$ cd ../graphsurgeon/
$ pip install graphsurgeon-0.4.6-py2.py3-none-any.whl
Defaulting to user installation because normal site-packages is not writeable
Processing ./graphsurgeon-0.4.6-py2.py3-none-any.whl
Installing collected packages: graphsurgeon
Successfully installed graphsurgeon-0.4.6
$ cd ../onnx_graphsurgeon/
$ pip install onnx_graphsurgeon-0.3.12-py2.py3-none-any.whl
Defaulting to user installation because normal site-packages is not writeable
Processing ./onnx_graphsurgeon-0.3.12-py2.py3-none-any.whl
Collecting onnx
Using cached onnx-1.12.0.tar.gz (10.1 MB)
Preparing metadata (setup.py) ... done
Requirement already satisfied: numpy in /home/ym/.local/lib/python3.6/site-packages (from onnx-graphsurgeon==0.3.12) (1.19.5)
Requirement already satisfied: protobuf<=3.20.1,>=3.12.2 in /home/ym/.local/lib/python3.6/site-packages (from onnx->onnx-graphsurgeon==0.3.12) (3.17.3)
Requirement already satisfied: typing-extensions>=3.6.2.1 in /home/ym/.local/lib/python3.6/site-packages (from onnx->onnx-graphsurgeon==0.3.12) (3.7.4.3)
Requirement already satisfied: six>=1.9 in /home/ym/.local/lib/python3.6/site-packages (from protobuf<=3.20.1,>=3.12.2->onnx->onnx-graphsurgeon==0.3.12) (1.15.0)
Building wheels for collected packages: onnx
Building wheel for onnx (setup.py) ... error
$ sudo apt-get update
...
W: GPG error: http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY A4B469963BF863CC
E: The repository 'http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.
$ git clone https://github.com/udhos/update-golang
cd update-golang
sudo ./update-golang.sh
사용하는 shell 확인
$ ls /home/{user} -alh
total 72K
drwxr-xr-x 9 ym ym 4.0K Oct 4 10:45 .
drwxr-xr-x 3 root root 4.0K Aug 22 11:56 ..
-rw------- 1 ym ym 6.5K Oct 4 11:32 .bash_history
-rw-r--r-- 1 ym ym 220 Aug 22 11:56 .bash_logout
-rw-r--r-- 1 ym ym 3.8K Oct 4 11:36 .bashrc
...
$ wget https://github.com/Kitware/CMake/releases/download/v3.24.2/cmake-3.24.2.tar.gz
$ tar -xvzf cmake-3.24.2.tar.gz
$ cd cmake-3.24.2
$ ./bootstrap --prefix=/usr/local
$ make
$ make install
CMake Error at Utilities/cmcurl/CMakeLists.txt:591 (message): Could not find OpenSSL. Install an OpenSSL development package or configure CMake with -DCMAKE_USE_OPENSSL=OFF to build without OpenSSL.
The elements are GStreamer's basic construction blocks.
They process the ata as it flows downstream from the source elements (data producers) to the sink elements (data consumers), passing through filter elements.
// GstElement*
// gst_pipeline_new(const gchar* name);
// <<< MT safe >>>
/* Create the empty pipeline */
pipeline = gst_pipeline_new("test-pipeline");
// gboolean
// gst_bin_add(
// GstBin* bin,
// GstElement* element);
//
// gst_bin_add_many(
// GstBin* bin,
// GstElement* element_1,
// ...); // NULL-terminated list of elements
/* Build the pipeline */
gst_bin_add_many(GST_BIN(pipeine), source, sink, NULL);
if (!gst_element_link(source, sink)) {
g_printerr("Elements could not be linked.\n");
gst_object_unref(pipeline);
return -1;
}
Properties
GStreamer elements are all a particular kind of GObject, which is the entity offering property facilities.
// void
// g_object_set(
// GObject* object,
// const gchar* first_property_name,
// ...); // NULL-terminated list of property-name, property-value pairs
/* Modify the source's properties */
g_object_set(source, "pattern", 0, NULL);
Error checking
// GstStateChangeReturn
// gst_element_set_state(
// GstElement* element,
// GstState state);
/* Start playing */
rv = gst_element_set_state(pipeline, GST_STATE_PLAYING);
if (rv == GST_STATE_CHANGE_FAILURE) {
g_printerr("Unable to set the pipeline to the playing state.\n");
gst_object_unref(pipeline);
return -1;
}
/* Wait until error or EOS */
bus = gst_element_get_bus(pipeline);
msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE,
GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
/* Parse message */
if (msg != NULL) {
GError* err;
gchar* debug_info;
switch (GST_MESSAGE_TYPE(msg)) {
case GST_MESSAGE_ERROR:
gst_message_parse_error(msg, &err, &debug_info);
g_printerr("Error received from element %s: %s\n",
GST_OBJECT_NAME(msg->src), err->message);
g_printerr("Debugging information: %s\n",
debug_info ? debug_info : "none");
g_clear_error(&err);
g_free(debug_info);
break;
case GST_MESSAGE_EOS:
g_print("End-Of-Stream reached.\n");
break;
}
gst_message_unref(msg);
}
typedef struct _CustomData {
GstElement* pipeline;
GstElement* source;
GstElement* convert;
GstElement* sink;
} CustomData;
/* Handler for the pad-added signal */
static void pad_added_handler(GstElement* src, GstPad* pad, CustomData* data);
/* Create the elements */
data.source = gst_element_factory_make("uridecodebin", "source");
data.convert = gst_element_factory_make("audioconvert", "convert");
data.resample = gst_element_factory_make("audioresample", "resample");
data.sink = gst_element_factory_make("autoaudiosink", "sink");
/* Create the empty pipeline */
data.pipeline = gst_pipeline_new("test-pipeline");
/* Build the pipeline */
gst_bin_add_many(GST_BIN(data.pipeline),
data.source, data.convert, data.resample, data.sink, NULL);
if (!gst_element_link_many(data.convert, data.resample, data.sink, NULL)) {
g_printerr("Elements could not be linked.\n");
gst_object_unref(data.pipeline);
return -1;
}
Signals
/* Connect to the pad-added signal */
g_signal_connect(data.source, "pad-added",
G_CALLBACK(pad_added_handler), &data);
Callback
/* This function will be called by the pad-added signal */
static void pad_added_handler(
GstElement* src,
GstPad* new_pad,
CustomData* data)
{
GstPad* sink_pad = gst_element_get_static_pad(data->convert, "sink");
GstPadLinkReturn rv;
GstCaps* new_pad_caps = NULL;
GstStructure* new_pad_struct = NULL;
const gchar* new_pad_type = NULL;
g_print("Received new pad '%s' from '%s':\n",
GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(src));
/* If our converter is already linked, we have nothing to do here */
if (gst_pad_is_linked(sink_pad)) {
g_print("We are already linked. Ignoring.\n");
goto exit;
}
/* Check the new pad's type */
new_pad_caps = gst_pad_get_current_caps(new_pad);
new_pad_struct = gst_caps_get_structure(new_pad_caps, 0);
new_pad_type = gst_structure_get_name(new_pad_struct);
if (!g_str_has_prefix(new_pad_type, "audio/x-raw")) {
g_print("It has type '%s' which is not raw audio. Ignoring.\n", new_pad_type);
goto exit;
}
/* Attempt the link */
rv = gst_pad_link(new_pad, sink_pad);
if (GST_PAD_LINK_FAILED(rv))
g_print("Type is '%s' but link failed.\n", new_pad_type);
else
g_print("Link succeeded (type '%s').\n", new_pad_type);
exit:
/* Unreference the new pad's caps, if we got them */
if (new_pad_caps)
gst_caps_unref(new_pad_caps);
/* Unreference the sink pad */
gst_object_unref(sink_pad);
}
GStreamer States
State
Description
NULL
the NULL state or initial state of an element.
READY
the element is ready to go to PAUSED.
PAUSED
the element is PAUSED, it is ready to accept and process data. Sink elements however only accept one buffer and then block.
PLAYING
the element is PLAYING, the clock is running and the data is flowing.
Multi-threading
/* Create the elements */
audio_source = gst_element_factory_make("audiotestsrc", "audio_source");
tee = gst_element_factory_make("tee", "tee");
audio_queue = gst_element_factory_make("queue", "audio_queue");
audio_convert = gst_element_factory_make("audioconvert", "audio_convert");
audio_resample = gst_element_factory_make("audioresample", "audio_resample");
audio_sink = gst_element_factory_make("autoaudiosink", "audio_sink");
video_queue = gst_element_factory_make("queue", "video_queue");
visual = gst_element_factory_make("wavescope", "visual");
video_convert = gst_element_factory_make("videoconvert", "video_convert");
video_sink = gst_element_factory_make("autovideosink", "video_sink");
/* Create the empty pipeline */
pipeline = gst_pipeline_new("test-pipeline");
/* Configure element */
g_object_set(audio_source, "freq", 215.0f, NULL);
g_object_set(visual,
"shader", 0,
"style", 1, NULL);
/* Link all elements that can be automatcially linked because they have "Always" pads */
gst_bin_add_many(GST_BIN(pipeline),
audio_source, tee, audio_queue, audio_convert, audio_resample, audio_sink,
video_queue, visual, video_convert, video_sink, NULL);
gst_element_link_many(audio_source, tee, NULL);
gst_element_link_many(audio_queue, audio_convert, audio_resample, audio_sink, NULL);
gst_element_link_many(video_queue, visual, video_convert, video_sink, NULL);
/* Manually link the Tee, which has "Request" pads */
tee_audio_pad = gst_element_request_pad_simple(tee, "src_%u");
queue_audio_pad = gst_element_get_static_pad(audio_queue, "sink");
tee_video_pad = gst_element_request_pad_simple(tee, "src_%u");
queue_video_pad = gst_element_get_static_pad(video_queue, "sink");
gst_pad_link(tee_audio_pad, queue_audio_pad);
gst_pad_link(tee_video_pad, queue_video_pad);
gst_object_unref(queue_audio_pad);
gst_object_unref(queue_video_pad);
/* Start playing the pipeline */
gst_element_set_state(pipeline, GST_STATE_PLAYING);
/* Wait until error or EOS */
bus = gst_element_get_bus(pipeline);
msg = gst_bus_time_pop_filtered(bus,
GST_CLOCK_TIME_NONE,
GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
/* Release the request pads from the Tee, and unref them */
gst_element_release_request_pad(tee, tee_audio_pad);
gst_element_release_request_pad(tee, tee_video_pad);
gst_object_unref(tee_audio_pad);
gst_object_unref(tee_video_pad);
/* Free resources */
if (msg)
gst_message_unref(msg);
gst_object_unref(bus);
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
#define CHUNK_SIZE 1024 /* Amount of bytes we are sending in each buffer */
#define SAMPLE_RATE 44100 /* Samples per second we are sending */
typedef struct _CustomData {
GstElement *pipeline;
GstElement *app_source, *tee;
GstElement *audio_queue, *audio_convert1, *audio_resample, *audio_sink;
GstElement *video_queue, *audio_convert2, *visual, *video_convert, *video_sink;
GstElement *app_queue, *app_sink;
guint64 num_samples; /* Number of samples generated so far (for timestamp generation) */
gfloat a, b, c, d; /* For waveform generation */
guint sourceid; /* To control the GSource */
GMainLoop *main_loop; /* GLib's Main Loop */
} CustomData;
/**
* This method is called by the idle GSource in the mainloop,
* to feed CHUNK_SIZE bytes into appsrc.
* The idle handler is added to the mainloop
* when appsrc requests us to start sending data (need-data signal)
* and is removed when appsrc has enough data (enough-data signal).
*/
static gboolean push_data(CustomData* data)
{
GstBuffer* buffer;
GstFlowReturn rv;
int i;
GstMapInfo map;
gint16* raw;
gint num_samples = CHUNK_SIZE / 2; /* Because each sample is 16 bits */
gfoat freq;
/* Create a new empty buffer */
buffer = gst_buffer_new_add_alloc(CHUNK_SIZE);
/* Set its timestamp and duration */
GST_BUFFER_TIMESTAMP(buffer) = gst_util_uint64_scale(data->num_samples, GST_SECOND, SAMPLE_RATE);
GST_BUFFER_DURATION(buffer) = gst_util_uint64_scale(num_samples, GST_SECOND | SAMPLE_RATE);
/* Generate some psychodelic waveforms */
gst_buffer_map(buffer, &map, GST_MAP_WRITE);
raw = (gint16*)map.data;
data->c += data->d;
data->d -= data->c / 1000;
freq = 1100 + 1000 * data->d;
for (i = 0; i < num_samples; ++i) {
data->a += data->b;
data->b -= data->a / freq;
raw[i] = (gint16)(500 * data->a);
}
gst_buffer_unmap(buffer, &map);
data->num_samples *= num_samples;
/* Push the buffer into the appsrc */
g_signal_emit_by_name(data->app_source, "push-buffer", buffer, &rv);
/* Free the buffer now that we are done with it */
gst_buffer_unref(buffer);
if (rv != GST_FLOW_OK) {
/* We got some error, stop sending data */
return FALSE;
}
return TRUE;
}
/**
* This signal callback triggers when appsrc needs data.
* Here, we add an idle handler to the mainloop
* to start pushing data into the appsrc
*/
static void start_feed(GstElement* source, guint size, CustomData* data)
{
if (data->sourceid == 0) {
g_print("Start feeding\n");
data->sourceid = g_idle_add((GSourceFunc)push_data, data);
}
}
/**
* This callback triggers when appsrc has enough data and we can stop sending.
* We remove the idle handler from the mainloop
*/
static void stop_feed(GstElement* source, CustomData* data)
{
if (data->sourceid != 0) {
g_print("Stop feeding\n");
g_source_remove(data->sourceid);
data->sourceid = 0;
}
}
/* The appsink has received a buffer */
static GstFlowReturn new_sample(GstElement* sink, CustomData* data)
{
GstSample* sample;
/* Retrieve the buffer */
g_signal_emit_by_name(sink, "pull-sample", &sample);
if (sample) {
/* The only thing we do in this example is print a * to indicate a received buffer */
g_print("*");
gst_sample_unref(sample);
return GST_FLOW_OK;
}
return GST_FLOW_ERROR;
}
/**
* this function is called when an error message is posted on the bus
*/
static void error_cb(GstBus* bus, GstMessage* msg, CustomData* data)
{
GError* err;
gchar* debug_info;
/* Print error details on the screen */
gst_message_parse_error(msg, &err, &debug_info);
g_printerr("Error received from element %s: %s\n",
GST_OBJECT_NAME(msg->src), err->message);
g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none");
g_clear_error(&err);
g_free(debug_info);
g_main_loop_quit(data->main_loop);
}
It manages all aspects of media playback, from source to diaplay, passing through demuxing and decoding. It is so flexible and has so many options.
uridecodebin
This element decodes data from a URI into raw media. It selects a source element that can handle the given URI scheme and connects it to a decodebin element. It acts like a demuxer, so it offers as many source pads as streams are found in the media.
decodebin
This element automatically constructs a decoding pipeline using available decoders and demuxers via auto-plugging until raw media is obtained.
File input/output
filesrc
This element reads a local file and produces media with ANY Caps. If you want to obtain the correct Caps for the media, explore the stream by using a typefind element or by setting the typefind property of filesrc to TRUE.
filesink
This element writes to a file all the media it receives. Use the location property to specify the file name.
Network
souphttpsrc
This element receives data as a client over the network via HTTP using the libsoup library. Set the URL to retrieve through the location property.
Test media generation
videotestsrc
This element produces a video pattern (selectable among many different options with the pattern property). Use it to test video pipelines.
audiotestsrc
This element produces a audio wave (selectable among many different options with the wave property). Use it to test audio pipelines.
Video adapters
videoconvert
This element converts from one color space to another one. It can also convert between different YUV formats or RGB format arrangements. This is normally your first choice when solving negotiation problems. When not needed, because its upstream and downstream elements can already understand each other, it acts in pass-through mode having minimal impact on the performance. As a rule of thumb, always use videoconvert whenever you use elements whose Caps are unknown at design time, like autovideosink, or that can vary depending on external factors, like user-provided file.
videorate
This element takes an incoming stream of time-stamped video frames and produces a stream that matches the source pad's frame rate. The correction is performance by dropping and duplicating frames, no fancy algorithm is used to interpolate frames. This is useful to allow elements requiring different frame rates to link. As with the other adapters, if it is not needed (because there is a frame rate on which both Pads can agree), it acts in pass-through mode and does not ipact performance. It is therefore a good idea to always use it whenever the actual frame rate is unknown at design time, just in case.
videoscale
This element resizes video frames. By default the element tries to negotiate to the same size on the source and sink Pads so that no scaling is needed. It it therefore safe to insert this element in a pipeline to get more robust behavior without any cost if no scaling is needed. This element supports a wide range of color spaces including various YUV and RGB formats and is therefore generally able to operate anywhere in a pipeline. If the video is to be output to a window whose size is controlled by the user, it is a good idea to use a videoscale element, since not all video sinks are capable of performing scaling operations.
Audio adapters
audioconvert
This element converts raw audio buffers between various possible formats. It supports - integer to float conversion, -width/depth conversion, -signedness and -endianness conversion and -channel transformations.
Like videoconvert does for video, you use this to solve negotiation problems with audio, and it is generally safe to use it liberally, since this element does nothing if it is not needed.
audioresample
This element resamples raw audio buffers to different sampling rates using a configurable windowing function to enhance quality
audiorate
This element takes an incoming stream of time-stamped raw audio frames and produces a perfect stream by inserting or dropping samples as needed. It does not allow the sample rate to be changed as videorate does, it just fills gaps and removes overlapped samples so the output stream is continuous and “clean”.
It is useful in situations where the timestamps are going to be lost (when storing into certain file formats, for example) and the receiver will require all samples to be present. It is cumbersome to exemplify this, so no example is given.
Multithreading
queue
Basically, a queue performs two tasks:
Data is queued until a selected limit is reached. Any attempt to push more buffers into the queue blocks the pushing thread until more space becomes available.
The queue creates a new thread on the source Pad to decouple the processing on sink and source Pads.
Additionally, queue triggers signals when it is about to become empty or full (according to some configurable thresholds), and can be instructed to drop buffers instead of blocking when it is full.
queue2
queue2 performs the two tasks listed above for queue, and, additionally, is able to store the received data (or part of it) on a disk file, for later retrieval. It also replaces the signals with the more general and convenient buffering messages described in Basic tutorial 12: Streaming. As a rule of thumb, prefer queue2 over queue whenever network buffering is a concern to you. See Basic tutorial 12: Streaming for an example (queue2 is hidden inside playbin).
mutiqueue
This element provides queues for multiple streams simultaneously, and eases their management,
by allowing some queues to grow if no data is being received on other streams,
by allowing some queues to drop data if they are not connected to anything (instead of returning an error, as a simpler queue would do).
Additionally, it synchronizes the different streams, ensuring that none of them goes too far ahead of the others. This is an advanced element. It is found inside decodebin, but you will rarely need to instantiate it yourself in a normal playback application.
tee
This element splits data to multiple pads. Splitting the data flow is useful, for example, when capturing a video where the video is shown on the screen and also encoded and written to a file. Another example is playing music and hooking up a visualization module. One needs to use separate queue elements in each branch to provide separate threads for each branch. Otherwise a blocked dataflow in one branch would stall the other branches.
Capabilities
capfilter
When building a pipeline programmatically, Caps filters are implemented with the capsfilter element. This element does not modify data as such, but enforces limitations on the data format.
typefind
This element determines the type of media a stream contains. It applies typefind functions in the order of their rank. Once the type has been detected it sets its source Pad Caps to the found media type and emits the have-type signal.
It is instantiated internally by decodebin, and you can use it too to find the media type, although you can normally use the GstDiscoverer which provides more information (as seen in Basic tutorial 9: Media information gathering).
Debugging
fakesink
This sink element simply swallows any data fed to it. It is useful when debugging, to replace your normal sinks and rule them out of the equation. It can be very verbose when combined with the -v switch of gst-launch-1.0, so use the silent property to remove any unwanted noise.
identity
This is a dummy element that passes incoming data through unmodified. It has several useful diagnostic functions, such as offset and timestamp checking, or buffer dropping. Read its documentation to learn all the things this seemingly harmless element can do.
$ cat /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.20.96.1
PS C:\dev\vcpkg> .\vcpkg integrate install
Applied user-wide integration for this vcpkg root.
All C++ projects can now #include any installed libraries.
Linking will be handled automatically.
Installing new libraries will make them instantly available.
Remove
PS C:\dev\vcpkg> .\vcpkg integrate remove
CMake (Toolchain File)
The best way to use installed libraries with cmake is via the toolchain file scripts/buildsystems/vcpkg.cmake.
To use this file, you simply need to add it onto your CMake command line as:
If you are using CMake through Open Folder with Visual Studio you can define CMAKE_TOOLCHAIN_FILE by adding a "variables" section to each of your CMakeSettings.json configurations:
Note: It might be necessary to delete the CMake cache folder of each modified configuration, to force a full regeneration. In the CMake menu, under Cache (<configuration name>) you'll find Delete Cache Folders.
Now let's make a simple CMake project with a main file.
Then, we build our project in the normal CMake way:
PS D:\src\cmake-test> mkdir build
PS D:\src\cmake-test> cd build
PS D:\src\cmake-test\build> cmake .. "-DCMAKE_TOOLCHAIN_FILE=D:\src\vcpkg\scripts\buildsystems\vcpkg.cmake"
// omitted CMake output here //
-- Build files have been written to: D:/src/cmake-test/build
PS D:\src\cmake-test\build> cmake --build .
// omitted MSBuild output here //
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.38
PS D:\src\cmake-test\build> .\Debug\main.exe
3.15.0
Note: The correct sqlite3.dll is automatically copied to the output folder when building for x86-windows. You will need to distribute this along with your application.
Handling libraries without native cmake support
Unlike other platforms, we do not automatically add the include\ directory to your compilation line by default.
If you're using a library that does not provide CMake integration, you will need to explicitly search for the files and add them yourself using find_path() and find_library().
# To find and use catch
find_path(CATCH_INCLUDE_DIR catch.hpp)
include_directories(${CATCH_INCLUDE_DIR})
# To find and use azure-storage-cpp
find_path(WASTORAGE_INCLUDE_DIR was/blob.h)
find_library(WASTORAGE_LIBRARY wastorage)
include_directories(${WASTORAGE_INCLUDE_DIR})
link_libraries(${WASTORAGE_LIBRARY})
# Note that we recommend using the target-specific directives for a cleaner cmake:
# target_include_directories(main ${LIBRARY})
# target_link_libraries(main PRIVATE ${LIBRARY})
If the collection is generic, then items are compared for equality according to the following guidelines:
If type T implements the IEquatable<T> generic interface, then the equality comparer is the Equals method of that interface.
If type T does not implement IEquatable<T>, Object.Equals is used.
In addition, some constructor overloads for dictionary collections an IEqualityComparer<T> implementation, which is used to compare keys for equality.
We recommend that you derive from the EqualityComparer<T> class instead of implementing the IEqualityComparer<T> interface, because the EqualityComparer<T> class tests for equality using the IEquatable<T>.Equals method instead of the Object.Equals method.
Determine Sort Order
For comparing objects, there is the concept of a default comparer and an explicit comparer.
The default comparer relies on at least one of the objects being compared to implement the IComparable interface.
For a generic collection, equality comparison is determined according to the following:
If type T implements the System.IComparable<T> generic interface, then the default comparer is the IComparable<T>.CompareTo(T) method of that interface.
If type T implements the non-generic System.IComparable interface, then the default comparer is the IComparable.CompareTo(Object) method that interface.
If type T doen't implement either interface, then there is no default comparer, and a comparer or comparison delegate must be provided explicity.
Example:
using System;
using System.Collections.Generic;
// Simple business object. A PartId is used to identify the
// type of part but the part name can change.
public class Part : IEquatable<Part>, IComparable<Part>
{
public string PartName { get; set; }
public int PartId { get; set; }
public override string ToString() =>
$"ID: {PartId} Name: {PartName}";
public override bool Equals(object obj) =>
(obj is Part part)
? Equals(part)
: false;
public int SortByNameAscending(string name1, string name2) =>
name1?.CompareTo(name2) ?? 1;
// Default comparer for Part type.
// A null value means that this object is greater.
public int CompareTo(Part comparePart) =>
comparePart == null ? 1 : PartId.CompareTo(comparePart.PartId);
public override int GetHashCode() => PartId;
public bool Equals(Part other) =>
other is null ? false : PartId.Equals(other.PartId);
// Should also override == and != operators.
}
public class Example
{
public static void Main()
{
// Create a list of parts.
var parts = new List<Part>
{
// Add parts to the list.
new Part { PartName = "regular seat", PartId = 1434 },
new Part { PartName = "crank arm", PartId = 1234 },
new Part { PartName = "shift lever", PartId = 1634 },
// Name intentionally left null.
new Part { PartId = 1334 },
new Part { PartName = "banana seat", PartId = 1444 },
new Part { PartName = "cassette", PartId = 1534 }
};
// Write out the parts in the list. This will call the overridden
// ToString method in the Part class.
Console.WriteLine("\nBefore sort:");
parts.ForEach(Console.WriteLine);
// Call Sort on the list. This will use the
// default comparer, which is the Compare method
// implemented on Part.
parts.Sort();
Console.WriteLine("\nAfter sort by part number:");
parts.ForEach(Console.WriteLine);
// This shows calling the Sort(Comparison<T> comparison) overload using
// a lambda expression as the Comparison<T> delegate.
// This method treats null as the lesser of two values.
parts.Sort((Part x, Part y) =>
x.PartName == null && y.PartName == null
? 0
: x.PartName == null
? -1
: y.PartName == null
? 1
: x.PartName.CompareTo(y.PartName));
Console.WriteLine("\nAfter sort by name:");
parts.ForEach(Console.WriteLine);
/*
Before sort:
ID: 1434 Name: regular seat
ID: 1234 Name: crank arm
ID: 1634 Name: shift lever
ID: 1334 Name:
ID: 1444 Name: banana seat
ID: 1534 Name: cassette
After sort by part number:
ID: 1234 Name: crank arm
ID: 1334 Name:
ID: 1434 Name: regular seat
ID: 1444 Name: banana seat
ID: 1534 Name: cassette
ID: 1634 Name: shift lever
After sort by name:
ID: 1334 Name:
ID: 1444 Name: banana seat
ID: 1534 Name: cassette
ID: 1234 Name: crank arm
ID: 1434 Name: regular seat
ID: 1634 Name: shift lever
*/
}
}
using System;
using System.Collections.Generic;
class Program
{
static Dictionary<Box, String> boxes;
static void Main()
{
BoxSameDimensions boxDim = new BoxSameDimensions();
boxes = new Dictionary<Box, string>(boxDim);
Console.WriteLine("Boxes equality by dimensions:");
Box redBox = new Box(8, 4, 8);
Box greenBox = new Box(8, 6, 8);
Box blueBox = new Box(8, 4, 8);
Box yellowBox = new Box(8, 8, 8);
AddBox(redBox, "red");
AddBox(greenBox, "green");
AddBox(blueBox, "blue");
AddBox(yellowBox, "yellow");
Console.WriteLine();
Console.WriteLine("Boxes equality by volume:");
BoxSameVolume boxVolume = new BoxSameVolume();
boxes = new Dictionary<Box, string>(boxVolume);
Box pinkBox = new Box(8, 4, 8);
Box orangeBox = new Box(8, 6, 8);
Box purpleBox = new Box(4, 8, 8);
Box brownBox = new Box(8, 8, 4);
AddBox(pinkBox, "pink");
AddBox(orangeBox, "orange");
AddBox(purpleBox, "purple");
AddBox(brownBox, "brown");
}
public static void AddBox(Box bx, string name)
{
try
{
boxes.Add(bx, name);
Console.WriteLine("Added {0}, Count = {1}, HashCode = {2}",
name, boxes.Count.ToString(), bx.GetHashCode());
}
catch (ArgumentException)
{
Console.WriteLine("A box equal to {0} is already in the collection.", name);
}
}
}
public class Box
{
public Box(int h, int l, int w)
{
this.Height = h;
this.Length = l;
this.Width = w;
}
public int Height { get; set; }
public int Length { get; set; }
public int Width { get; set; }
}
class BoxSameDimensions : EqualityComparer<Box>
{
public override bool Equals(Box b1, Box b2)
{
if (b1 == null && b2 == null)
return true;
else if (b1 == null || b2 == null)
return false;
return (b1.Height == b2.Height &&
b1.Length == b2.Length &&
b1.Width == b2.Width);
}
public override int GetHashCode(Box bx)
{
int hCode = bx.Height ^ bx.Length ^ bx.Width;
return hCode.GetHashCode();
}
}
class BoxSameVolume : EqualityComparer<Box>
{
public override bool Equals(Box b1, Box b2)
{
if (b1 == null && b2 == null)
return true;
else if (b1 == null || b2 == null)
return false;
return (b1.Height * b1.Width * b1.Length ==
b2.Height * b2.Width * b2.Length);
}
public override int GetHashCode(Box bx)
{
int hCode = bx.Height * bx.Length * bx.Width;
return hCode.GetHashCode();
}
}
/* This example produces an output similar to the following:
*
Boxes equality by dimensions:
Added red, Count = 1, HashCode = 46104728
Added green, Count = 2, HashCode = 12289376
A box equal to blue is already in the collection.
Added yellow, Count = 3, HashCode = 43495525
Boxes equality by volume:
Added pink, Count = 1, HashCode = 55915408
Added orange, Count = 2, HashCode = 33476626
A box equal to purple is already in the collection.
A box equal to brown is already in the collection.
*
*/
using System;
using System.Collections;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
List<Box> Boxes = new List<Box>();
Boxes.Add(new Box(4, 20, 14));
Boxes.Add(new Box(12, 12, 12));
Boxes.Add(new Box(8, 20, 10));
Boxes.Add(new Box(6, 10, 2));
Boxes.Add(new Box(2, 8, 4));
Boxes.Add(new Box(2, 6, 8));
Boxes.Add(new Box(4, 12, 20));
Boxes.Add(new Box(18, 10, 4));
Boxes.Add(new Box(24, 4, 18));
Boxes.Add(new Box(10, 4, 16));
Boxes.Add(new Box(10, 2, 10));
Boxes.Add(new Box(6, 18, 2));
Boxes.Add(new Box(8, 12, 4));
Boxes.Add(new Box(12, 10, 8));
Boxes.Add(new Box(14, 6, 6));
Boxes.Add(new Box(16, 6, 16));
Boxes.Add(new Box(2, 8, 12));
Boxes.Add(new Box(4, 24, 8));
Boxes.Add(new Box(8, 6, 20));
Boxes.Add(new Box(18, 18, 12));
// Sort by an Comparer<T> implementation that sorts
// first by the length.
Boxes.Sort(new BoxLengthFirst());
Console.WriteLine("H - L - W");
Console.WriteLine("==========");
foreach (Box bx in Boxes)
{
Console.WriteLine("{0}\t{1}\t{2}",
bx.Height.ToString(), bx.Length.ToString(),
bx.Width.ToString());
}
Console.WriteLine();
Console.WriteLine("H - L - W");
Console.WriteLine("==========");
// Get the default comparer that
// sorts first by the height.
Comparer<Box> defComp = Comparer<Box>.Default;
// Calling Boxes.Sort() with no parameter
// is the same as calling Boxs.Sort(defComp)
// because they are both using the default comparer.
Boxes.Sort();
foreach (Box bx in Boxes)
{
Console.WriteLine("{0}\t{1}\t{2}",
bx.Height.ToString(), bx.Length.ToString(),
bx.Width.ToString());
}
// This explicit interface implementation
// compares first by the length.
// Returns -1 because the length of BoxA
// is less than the length of BoxB.
BoxLengthFirst LengthFirst = new BoxLengthFirst();
Comparer<Box> bc = (Comparer<Box>) LengthFirst;
Box BoxA = new Box(2, 6, 8);
Box BoxB = new Box(10, 12, 14);
int x = LengthFirst.Compare(BoxA, BoxB);
Console.WriteLine();
Console.WriteLine(x.ToString());
}
}
public class BoxLengthFirst : Comparer<Box>
{
// Compares by Length, Height, and Width.
public override int Compare(Box x, Box y)
{
if (x.Length.CompareTo(y.Length) != 0)
{
return x.Length.CompareTo(y.Length);
}
else if (x.Height.CompareTo(y.Height) != 0)
{
return x.Height.CompareTo(y.Height);
}
else if (x.Width.CompareTo(y.Width) != 0)
{
return x.Width.CompareTo(y.Width);
}
else
{
return 0;
}
}
}
// This class is not demonstrated in the Main method
// and is provided only to show how to implement
// the interface. It is recommended to derive
// from Comparer<T> instead of implementing IComparer<T>.
public class BoxComp : IComparer<Box>
{
// Compares by Height, Length, and Width.
public int Compare(Box x, Box y)
{
if (x.Height.CompareTo(y.Height) != 0)
{
return x.Height.CompareTo(y.Height);
}
else if (x.Length.CompareTo(y.Length) != 0)
{
return x.Length.CompareTo(y.Length);
}
else if (x.Width.CompareTo(y.Width) != 0)
{
return x.Width.CompareTo(y.Width);
}
else
{
return 0;
}
}
}
public class Box : IComparable<Box>
{
public Box(int h, int l, int w)
{
this.Height = h;
this.Length = l;
this.Width = w;
}
public int Height { get; private set; }
public int Length { get; private set; }
public int Width { get; private set; }
public int CompareTo(Box other)
{
// Compares Height, Length, and Width.
if (this.Height.CompareTo(other.Height) != 0)
{
return this.Height.CompareTo(other.Height);
}
else if (this.Length.CompareTo(other.Length) != 0)
{
return this.Length.CompareTo(other.Length);
}
else if (this.Width.CompareTo(other.Width) != 0)
{
return this.Width.CompareTo(other.Width);
}
else
{
return 0;
}
}
}
1. Output a list of installed packages into a requirements file (requirements.txt):
pip freeze > requirements.txt
2. Edit requirements.txt, and replace all '==' with '>='. Use the 'Replace All' command in the editor.
3. Upgrade all outdated packages:
pip install -r requirements.txt --upgrade
Updating All Packages In A Virtual Enviroment
The easiest way to update unpinned packages (i.e., packages that do not require a specific version) in a virtual environment is to run following Python script that makes use of pip:
import pkg_resources
from subprocess import call
for dist in pkg_resources.working_set:
call("python -m pip install --upgrade " + dist.<projectname>, shell=True)
Updating All Packages In A Pipenv Environment
The simplest way to update all the unpinned packages in a specific virtual environment created with pipenv is to do the following steps:
1. Activate the Pipenv shell that contains the packages to be upgraded:
connections to localhost:8000 are sent to port 80 in the container.
Known limitations, use cases, and workarounds
There is no docker0 bridge on Windows
I cannot ping my containers
Per-container IP addressing is not possible
Use cases and workarounds
I want to connect from a container to a service on the host
The host has a changing IP address (or none if you have no network access).
We recommend that you connect to the special DNS name host.docker.internal
which resolves to the internal IP address used by the host.
This is for development purpose and will not work in a production environment outside of Docker Desktop for Windows.
You can also reach the gateway using gateway.docker.internal.
Example:
1. Run the following command to start a simple HTTP server on port 8000.
python -m http.server 8000
2. Now, run a container, install curl, and try to connect to the host using the following commands:
$ docker run --rm -it alpine sh
# apk add curl
# curl http://gateway.docker.internal:8000
# exit
I want to connect to a container from Windows
Port forwarding works for localhost; --publish, -p, or -P all work.
Ports exposed from Linux are forwarded to the host.
Our current recommendation is to publish a port, or to connect from another container.
This is what you need to do even on Linux if the container is on an overlay network, not a bridge network, as these are not routed.
For example, to run an nginx webserver:
$ docker run -d -p 80:80 --name webserver nginx
To clarify the syntax, the following two commands both publish container's port 80 to host's port 8000:
$ docker run --publish 8000:80 --name webserver nginx
$ docker run -p 8000:80 --name webserver nginx
To publish all ports, use the -P flag.
For example, the following command starts a container (in detached mode) and the -P flag publishes all exposed ports of the container to random ports on the host.
zk-single-kafka-single.yml을 기반으로 ym-test-z1-k1.yml 작성
$ docker-compose -f ym-test-z1-k1.yml up
vscode ➜ /com.docker.devenvironments.code (master ✗) $ sudo chmod 666 /var/run/docker.sock
vscode ➜ /com.docker.devenvironments.code (master ✗) $ export DOCKER_HOST_IP=192.168.65.100
vscode ➜ /com.docker.devenvironments.code (master ✗) $ docker-compose -f ym-test-z1-k1.yml up
Starting comdockerdevenvironmentscode_zoo1_1 ... done
Starting comdockerdevenvironmentscode_kafka1_1 ... error
ERROR: for comdockerdevenvironmentscode_kafka1_1 Cannot start service kafka1: Ports are not available: listen tcp 0.0.0.0:9999: bind: An attempt was made to access a socket in a way forbidden by its access permissions.
ERROR: for kafka1 Cannot start service kafka1: Ports are not available: listen tcp 0.0.0.0:9999: bind: An attempt was made to access a socket in a way forbidden by its access permissions.
ERROR: Encountered errors while bringing up the project.