View Full Version : AviSynth+ thread Vol.2
Llawliet
29th April 2023, 21:03
Nice point to check, thank you for your continued help
kedautinh12
1st May 2023, 05:32
L-SMASH-Works latest ver
https://github.com/HomeOfAviSynthPlusEvolution/L-SMASH-Works/releases
AviSynth: convert input filenames to UTF-8 (LWLibavVideo/AudioSource) (#30).
FFmpeg 41dd50a.
l-smash 2c0696c.
nv-codec-headers n12.0.16.0.
libxml2 v2.11.0.
gispos
4th May 2023, 21:04
Request to the Avisynth developers about ConvertToRGB32. Do you see a possibility to optimize the speed?
With a UHD video I get ~70 fps, after calling ConvertToRGB32 it's only ~28 fps.
With a 720 x 576 video I get ~2700 fps and after RGB conversion ~520 fps
It would be nice if the developers could squeeze out a few more fps.
FranceBB
4th May 2023, 21:42
Request to the Avisynth developers about ConvertToRGB32. Do you see a possibility to optimize the speed?
With a UHD video I get ~70 fps, after calling ConvertToRGB32 it's only ~28 fps.
With a 720 x 576 video I get ~2700 fps and after RGB conversion ~520 fps
It would be nice if the developers could squeeze out a few more fps.
Yeah, better performances would definitely be useful.
Out of curiosity, is your input Limited TV Range YUV?
I wonder if the speed penalty is because it's also converting the range from Limited to Full... Uhmmmmm
kedautinh12
5th May 2023, 05:50
Let's wait DTL explain it :D
L-SMASH-Works latest ver
https://github.com/HomeOfAviSynthPlusEvolution/L-SMASH-Works/releases
Errors
https://forum.doom9.org/showthread.php?p=1986659#post1986659
StainlessS
5th May 2023, 07:59
Request to the Avisynth developers about ConvertToRGB32. Do you see a possibility to optimize the speed?
With a UHD video I get ~70 fps, after calling ConvertToRGB32 it's only ~28 fps.
With a 720 x 576 video I get ~2700 fps and after RGB conversion ~520 fps
It would be nice if the developers could squeeze out a few more fps.
Well, this probably aint quite right but,
RGB32 is 32 bits per pixel,
YV12 is 12 bits per pixel.
32 / 12 = 2.666 {RGB has 2.666 times as many bits per pixel}
70fps / 2.666 = 26.25 FPS, {expected fps for RGB32}
So, maybe RGB32 processing not that bad really.
Somebody point out where I went wrong :)
EDIT: Also, the conversion itself adds another hit to speed.
It is right - if UHD in YV12 compressed format (2:1 to RGB24) it is about 2 times faster in memory transfer. RGB32 is even more slower. It is only issues of too slow memory subsystem of current computers. The actual computing dispatch ports at CPU core are fast enough. For 1 input frame and 1 output frame filter additional memory issues may be not applicable (though also possible at some chips).
In some future AVS core releases expected some more advanced protection from possible memory performance penalty after some redesign of virtual memory management - https://github.com/AviSynth/AviSynthPlus/issues/351 .
For possibly a bit better performance it may be recommended to use 'planar' RGB32 with separated planes. But memory performance at conversion from planar to interleaved and back is also not very good. Also high-quality decompression from YV12 to RGB may require many computing (up to Neural-Network AI-helpers) and may be really very slow. Because ugly old 4:2:x compression formats really lossy and makes irreversible damage to data - so only non-linear processing may somehow better recover from damaging errors.
kedautinh12
5th May 2023, 12:35
Errors
https://forum.doom9.org/showthread.php?p=1986659#post1986659
You need create issue to developer
https://github.com/HomeOfAviSynthPlusEvolution/L-SMASH-Works/issues
You need create issue to developer
https://github.com/HomeOfAviSynthPlusEvolution/L-SMASH-Works/issues
Thanks, I went to that link location, and Asd-g had been notified with a comment about errors, and provided 2 test files...
So I will check these out tomorrow. :D
gispos
5th May 2023, 18:20
First of all, I'm not saying that Avisynth is too slow! 70 fps is delivered and ~29 fps remain after the RGB conversion.
Also ~29 fps remain after the routine has been run. But how was it run through.
A simple example is to copy a bitmap memory.
I can copy each pixel individually, which then takes double the time if the number of pixels is doubled.
Or I copy a whole ScanLine * height in a loop which is faster even with double pixel count.
Or I copy the entire memory in one go. Which is even faster.
Please do not misunderstand, this is just an example to show that a doubling of a thing does not necessarily lead to a doubling of time.
This is mainly to let StainlessS mathematical calculations come to nothing. Little fun, don't be angry. :)
I always thought that drawing the frame takes the most time, which turned out to be a mistake.
The drawing itself costs about 3-4 fps, the bottleneck is the conversion to RGB.
Whether it's RGB24 or 32 doesn't really matter, in my experience these are negligible time quantities.
I am currently experimenting with a Prefetch(2,2) after ConvertToRGB32. This brings almost 30% more speed with YV12, but with YUV444P10 it is only 2-3 fps.
I can still think of parameters "Threads" and "GPU", whether feasible...?
You can take PC/Windows profiling tools like freeware AMD uProf and try to see if you can find any significant hotspots (not with load from memory) or scalar processing at ConvertToRGB and present these findings to AVS core developers as nice to have/fix peformance feature.
Also as usual the shortest possible script to reproduce the issue is required.
gispos
6th May 2023, 06:14
Possibilities exist, but will be too much for me, would have to learn from scratch.
https://docs.nvidia.com/cuda/npp/index.html
https://docs.nvidia.com/cuda/npp/group__yuv420torgb.html
Uploading to and downloading from external to host CPU data computing accelerator is typicaly slow and costly. The only reason to use very powerful external data computing accelerator if it can provide some state_of_art 4:2:0 to 4:4:4 decoding (expected non-linear AI-driven and Machine Learning based). So user can upload 4:2:0 dataset to external accelerator and patiently wait for result ready to download.
Same as we have some examples of neural-network trained to fight fields-aliasing in interlaced content (NNEDI3 field vertical 2x upsampler as example) - it is possible to design good non-linear decoder of YUV420/422 to 4:4:4 to fight design bugs of very old and ugly 4:2:0/4:2:2 compression.
If NVIDIA can provide some nice 4:2:0 to RGB decoder - it can be implemented as an external plugin and tested for quality. Though it mostly probably will be limited to CUDA and NVIDIA vendor hardware only.
gispos
6th May 2023, 14:21
I know that moving the data back and forth takes most of the time, but the process itself takes almost none.
I read something about 1500 fps, but I don't know how the quality is.
Was at the beginning when I asked "if there could be improvements" also only picked up by me because I thought the function has been around for a long time,
maybe it was completely forgotten. And it could not hurt to draw attention to it.... :)
About current DDR SDRAM performance (typically something around 50 GB/s): 4K UHD frame is 8 Msamples x 4 bytes in RGB32 (in 8bit) is 32 Mbytes in size. 28 fps mean about 900 MB/s only. It looks really available some better performance (though test script still not known).
With test script
ColorBars(3840, 2160, pixel_type="YV12")
ConvertToRGB32()
Prefetch(6)
I got 136 fps at i5-9600K CPU. It is about 4.3 GB/s possible RAM store speed (not sure if AVSmeter really make store ?). Also if I count everything right. So for 50 GB/s possible peak store performance is about 1500 fps (but also something is required to readback for next operation and so on - so if store and load from RAM it may be about 500 fps max).
Attempt to cache read :
ColorBars(3840, 2160, pixel_type="YV12")
Trim(1,1)
Loop(1000)
ConvertToRGB32()
Prefetch(6)
Make about same fps so possibly ColorBars already calculated only once and read from AVS cache.
Caching output of ConvertToRGB322() with
ColorBars(3840, 2160, pixel_type="YV12")
ConvertToRGB32()
Trim(1,1)
Loop(10000000)
Prefetch(6)
AVSmeter display something about 320000 fps - so it looks not make store and only skip pointer to provided frame from AVS cache. So to measure performance of convert() it may be require some more complex script. It is strange but changing chromaresample from point to spline64 close to change nothing in performance of ConvertToRGB32().
Resize test :
ColorBars(1920, 1080, pixel_type="YV12")
BicubicResize(width*2, height*2)
Prefetch(6)
With same 4K size of 2 chroma planes shows about 640fps. May be really dematrix from YUV to RGB is not very good optimized to AVX2. My AMD uProf is broken (no sampling driver start) at work PC so I can not make profile at this system now.
At development PC profiling shows it uses partially SSE and partially AVX2 computing (AVS+ 3.7.3). So if put all to AVX2 (and AVX512) it can be somehow faster. Also about 20% of time in the vcruntime140 - do not know why it looks like uses some library C functions but it is AVX2 also. But as I see the developers resources are very small in 2023 and it unlikely someone will make dematrix on new AVX SIMD very fast.
Add: Some idea from Dogway: If internal ConvertToRGB32 is too slow and old - you may try avsresize plugin possibly also capable of convert to RGB32 ?
It looks only support planar RGB32 but runs about 2 times faster at my chip i5-9600K:
LoadPlugin("avsresize.dll")
ColorBars(3840, 2160, pixel_type="YV12")
z_ConvertFormat(pixel_type="RGBAP8")
Prefetch(6)
About 250..260 fps. Though still not 500..600 fps as simple resize so dematrix calculation also takes some time and may be better opmitized too.
It looks only support planar RGB32 but runs about 2 times faster at my chip i5-9600K:
LoadPlugin("avsresize.dll")
ColorBars(3840, 2160, pixel_type="YV12")
z_ConvertFormat(pixel_type="RGBAP8")
Prefetch(6)
About 250..260 fps. Though still not 500..600 fps as simple resize so dematrix calculation also takes some time and may be better opmitized too.
If you use use_props=0 you will get better fps:
LoadPlugin("avsresize.dll")
ColorBars(3840, 2160, pixel_type="YV12")
z_ConvertFormat(pixel_type="RGBAP8", use_props=0)
Prefetch(6)
Yes - with z_ConvertFormat(pixel_type="RGBAP8", use_props=0) it run at about 300 fps.
gispos
6th May 2023, 22:23
And how do I get a packed RGB out of it that I can move to a DIB?
That probably costs the time saved. Or not?
And how do I get a packed RGB out of it that I can move to a DIB?
That probably costs the time saved. Or not?
ColorBars(3840, 2160, pixel_type="YV12")
z_ConvertFormat(pixel_type="RGBAP8", use_props=0)
ConvertToRGB32()
gispos
7th May 2023, 05:46
ColorBars(3840, 2160, pixel_type="YV12")
z_ConvertFormat(pixel_type="RGBAP8", use_props=0)
ConvertToRGB32()
Well, with use_props=0 it will be 2-3 fps faster but the colors are off and without use_props=0 the colors are correct but the whole thing is then slower than a single ConvertToRGB32.
This is a dead end.
It looks you use very old CPU to process UHD fast enough. May be SSE only. Typically developers optimize for AVX2 or later because developer resources are more and more limited and make and debug 3 functions SSE/AVX/AVX512 is more time and low reason in 202x optimize for very limited SSE. Each SIMD family may require different function design to be max efficient so it is no good simply expand SSE to AVX/AVX512 in many cases.
Typically today chips at motion pictures computing are limited with very low host RAM speed (about 50..100 GB/s for 2..4 channels DDR4/DDR5).
Each AVX512 dispatch port can process 64bytes cacheline at single clock for many simple operations. So 3 GHz chip with 8 cores of 24 GHz effective x 64 bytes can produce 1500 GBytes/sec store stream. Not any possible to handle with poor DDR-SDRAM. Only new HBM RAM at special compute boards can reach about 2 TB/s at single board (old designs of Tesla A100 accelerator). New and future HBM RAM may provide something about 10 TB/s at enduser machine in 202x if everything will go fine enough.
gispos
7th May 2023, 11:53
It looks you use very old CPU to process UHD fast enough. May be SSE only. ....
You are right, my CPU is a bit older. i7 4770 K with 4 cores and 8 threads.
But AVX2 is available: Intel® SSE4.1, Intel® SSE4.2, Intel® AVX2
and with 3.9 GHz it is also not the slowest... at least I thought so far.
You wrote that you get 300 fps with your i5... I achieve just half ~160 fps. With what did you measure it?
Then it's about time for something new.
StainlessS
7th May 2023, 12:51
I think I read somewhere that early version of AVX2 (ie Gen 4, Haswell) was 'poorly implemented'.
Was not properly fixed till 1 or 2 generations later.
Could not find any reference to above prob on Wikipedia "Advanced Vector Extensions" page, maybe I imagined it.
EDIT: Back when I was looking for a 2nd user i7 machine, I had initially figured on a i7-4790(K),
but on reading about above, I dropped the idea and decided 6th Gen (skylake) or above only,
as it happens I got 8th Gen i7, with 6C/12T instead of 6th Gen 4C/8T.
For comparing 2 processors google eg
"i7-4790K" vs "i7-6700K"
https://www.google.co.uk/search?q=%22i7-4790K%22+vs+%22i7-6700K%22&iflsig=AOEireoAAAAAZFeiceXKk3yVs6ov-AmZEuB9uUTPb-FQ
"i7-4790K" vs "i7-8700K"
https://www.google.co.uk/search?q=%22i7-4790K%22+vs+%22i7-8700K%22&iflsig=AOEireoAAAAAZFejVlqp958dTYNrbEGw_JGC2uZCi4yR
Quoted processor names, else might list some comparisons for close but not exact cpu's you want to compare.
Boulder
7th May 2023, 13:47
The performance issue with AVX2 was in older Ryzens, it was not a true implementation but an emulated one. I think the 3000-series had a real AVX2 capability.
"i7 4770 K with 4 cores"
But it is only 4th generation intel Core. DDR3 RAM of 25 GB/s only max. Hyperthreading looks like no helps any at poor endusers chips at AVS processing. At expensive Xeons with much better memory controller and larger cache and more RAM channels it may add about 20%.
My example of 300-fps i5-9600K is 9th generation and 6 real cores and DDR4 RAM of 41 GB/s max.
I test with running script with AVSmeter64.
In 202x it is recommended something may be possible at endusers desktops like CPU with AVX512 and 4 channels of DDR5 (may be up to 200 GB/s). Mostly frequent at poor endusers market looks like non-AVX512 chip with only 2 channels of DDR5.
Good starter Workstation is today something about many cores (>10) Xeon with AVX512 all cores default and 4..6 channels of DDR4 at least. Top Xeons Platinum may reach 8..12 channels of DDR4. Possible new Xeons with 4..6 channels of DDR5 is better.
Well, with use_props=0 it will be 2-3 fps faster but the colors are off and without use_props=0 the colors are correct but the whole thing is then slower than a single ConvertToRGB32.
To get correct colours at YUV to RGB dematrix you need to provide correct matrix data to z_ConvertFormat (if you disable frame props - they can handle required metadata automatically).
See string colorspace_op = at http://avisynth.nl/index.php/Avsresize . It is required to set matS param at least properly.
gispos
7th May 2023, 14:41
Then I'll have to take a look. I also always pay attention to the TDP, my CPU has only 65 watts maximum. For heating the apartment I have a heater. :)
VoodooFX
7th May 2023, 17:09
What's the problem with the script below?
v=ColorBars.ConvertToYV12
c=v.ConvertToYV24.Crop(10,10,91,90)
v.Overlay(c,x=50,y=50)
https://i.imgur.com/XyCzFAa.png
Reading about Overlay (http://avisynth.nl/index.php/Overlay) I don't expect such error.
kedautinh12
7th May 2023, 17:12
In crop change number to multiple of 2
VoodooFX
7th May 2023, 17:17
In crop change number to multiple of 2
I'm not interested in that.
kedautinh12
7th May 2023, 17:50
I'm not interested in that.
please read Crop restrictions at here:
http://avisynth.nl/index.php/Crop
poisondeathray
7th May 2023, 18:00
please read Crop restrictions at here:
http://avisynth.nl/index.php/Crop
ConvertToYV24 for the overlay layer means 4:4:4. There are no crop restrictions for progressive video
I believe the old overlay behaviour was everything got converted to 4:4:4 internally...
Now
http://avisynth.nl/index.php/Overlay
bool use444 = true
AVS+ If set to false, Overlay uses conversionless mode where possible instead of going through YUV 4:4:4.
false when mode="blend", "luma" or "chroma and format is YUV420/YUV422 (YV12/YV16). Original format is kept throughout the whole process, no 4:4:4 conversion occurs.
But it's false, when format is YUV420 - Since base layer is 4:2:0 - it's correct behaviour according to documentation
So the answer is set use444=true , or ConvertToYV24 beforehand
v.Overlay(c,x=50,y=50, use444=true)
VoodooFX
7th May 2023, 18:01
please read Crop restrictions at here:
http://avisynth.nl/index.php/Crop
You should read them: "no restriction".
VoodooFX
7th May 2023, 18:18
@poisondeathray
Thanks, I didn't read "use444" section to the end, just saw "bool use444 = true", maybe it should be changed to something like "bool use444 = [adaptive]" in wiki.
Well, with use_props=0 it will be 2-3 fps faster but the colors are off and without use_props=0 the colors are correct but the whole thing is then slower than a single ConvertToRGB32.
This is a dead end.
ColorBars(3840, 2160, pixel_type="YV12")
z_ConvertFormat(pixel_type="RGBAP8", use_props=0, cpu_type="avx2")
ConvertToRGB32()
Trim(0, 1000)
~70fps (cpu freq AVX2@4400)
ColorBars(3840, 2160, pixel_type="YV12")
z_ConvertFormat(pixel_type="RGBAP8", use_props=0, cpu_type="avx512f")
ConvertToRGB32()
Trim(0, 1000)
~76fps (cpu freq AVX512@3800)
ColorBars(3840, 2160, pixel_type="YV12")
ConvertToRGB32()
Trim(0, 1000)
~54fps
Aboult colors off: as @DTL mentioned - you need to set every value for colorspace_op=x:x:x:x=>y:y:y:y and for chromaloc_op=x:y (for example, z_ConvertFormat(pixel_type="RGBAP8", colorspace_op="2020:2020:2020:l=>rgb:2020:2020:f", chromaloc_op="top_left=>left") otherwise using z_ConvertFormat(pixel_type="RGBAP8", use_props=0") will use default values (170m=>rgb).
"~76fps (cpu freq AVX512@3800)"
What AVX512 chip provide so poor fps ? Or it is single threaded compare ? If it is really dematrix math limited processing - it expected to have much more benefit from AVX512 over AVX2.
Also do different UV planes scaling engine can provide some quality/performance balance ? Default scaling engine is fastest possible ?
"ConvertToRGB32()
~54fps (cpu freq AVX512@3800)"
Do current AVS core really go to AVX512 at ConvertToRGB32 ?
gispos
7th May 2023, 20:50
Aboult colors off: as @DTL mentioned - you need to set every value for colorspace_op=x:x:x:x=>y:y:y:y and for chromaloc_op=x:y (for example, z_ConvertFormat(pixel_type="RGBAP8", colorspace_op="2020:2020:2020:l=>rgb:2020:2020:f", chromaloc_op="top_left=>left") otherwise using z_ConvertFormat(pixel_type="RGBAP8", use_props=0") will use default values (170m=>rgb).
Without prefetch I just reach 38 fps, with Prefetch(2) it is 78 fps, which is 14 fps faster than with a single ConvertToRGB and Prefetch(2).
ColorBars(3840, 2160, pixel_type="YV12")
z_ConvertFormat(pixel_type="RGBAP8", colorspace_op="709:709:709:l=>rgb:709:709:f", chromaloc_op="top_left=>left")
prefetch(2)
ConvertToRGB32()
But it's hard to convert the whole z_Format stuff into code.
To the YV24 discussion above:
I had not known that YV24 can be cropped without restriction.
"with Prefetch(2) it is 78 fps,"
For your 4 core CPU optimal prefetch may be 4 (may be try a bit higher to see if there will be any visible benefit from hyperthreading).
"~76fps (cpu freq AVX512@3800)"
What AVX512 chip provide so poor fps ? Or it is single threaded compare ?
The used scripts are posted - no prefetch.
Edit:
"ConvertToRGB32()
~54fps (cpu freq AVX512@3800)"
Do current AVS core really go to AVX512 at ConvertToRGB32 ?
No. It's typo.
I expect users always set Prefetch to optimal value for current CPU used. So it is no good to post any prefetch value because it may be not optimal for most users and can confuse some users. So the script only contain filtergraph and user need to set optimal prefetch manually for best performance.
Btw using Converttorgb32() only for planar->packed causes ~30% fps drop. It seems a lot at first look. I have to test with libp2p (https://github.com/sekrit-twc/libp2p).
"using Converttorgb32() only for planar->packed causes ~30% fps drop. It seems a lot at first look."
It may greatly depend on current hardware memory subsystem design and partially on memory management in application. Planar to packed uses 4 read memory streams and 1 write stream. 4 read streams possibly can not cause set-associative cache aliasing conditions even with bad virtual memory addresses mapping but there may be other (many be more rare) memory addressing issues. Also if there is no really nice memory controller used - the 4 read RAM streams may cause significant overhead on SDRAM pages switching and it may be no good hided with SDRAM banks scheduling. Best RAM performance at simple memory controller designs typically only at the 1 read/write stream or simply memcpy of large block of contigous virtual memory addresses. Many read streams may already stress the really slow RAM (and with very slow random access).
Also real test may be better to perform at real muiti-frame source so AVS core with quickly thrash all data from CPU cache to RAM and the RAM performance will limit more. With single frame source it may be cached in CPU and show significantly better result. The 4K YV12 frame only 12 MB in size (?) so at large-L2/L3 CPUs may be completely cached and 4streams read performance may be much better. Though as ConvertToRGB32 mostly possibly uses cached store it may also replace some source data from L2/L3 (if it is of < 44 MB in size).
To make better syntetic test may be some Colorbars + Animate + Trim_range + Loop required. To force AVS create some 4K frames sequence like 10 in RAM in AVS-cache so when cycling via 10 frames in a loop the host CPU will re-read source data from RAM as with typical content processing.
" I have to test with libp2p."
It looks only SSE max and also at https://github.com/sekrit-twc/libp2p/blob/5e65679ae54d0f9fa412ab36289eb2255e341625/simd/p2p_sse41.cpp#L69 uses not very nice cast of integer treated data to float domain simply to use MM_TRANSPOSE4_PS macro. The CPU allow to make such casting but there is a performance penalty (sort of because microcode reconfigure dispatch ports for float processing or even need to resend data to float dispatch ports from integer). So in the instruction sets typically available visually equal instructions for integer and float data domain operating with same sets of bits. It is directly to avoid penalty from jumping between integer and float domains.
May be it is required to make integer MM_TRANSPOSE macro and it can add to performance. The shufps() is our common lovely instruction at the old SSE-era and may be not have integer version in the SSE instruction set. But already SSE2 have pshufpd() instruction for 128i shuffle. So it is available in SSE4.1 version of program.
Also AVX2 and AVX512 with larger register file may allow to grab more data for transpose and make less read/write bus switching. AVX512 also have more nice instructions for data shuffling/permutation. AVX2 allow destination operand to be different from sources. So it looks very outdated library if it is SSE only.
As an example of somehow good optimized for AVX512 chip SIMD program you may look at the https://github.com/Asd-g/AviSynth-vsTTempSmooth/blob/master/src/vsTTempSmooth_AVX512.cpp - it not very nice in syntax using repeating blocks of text but I currently not know how to make shorter syntax to increase 'workunit size' for each SIMD pass and also use some superscalar capability when available (dispatch >1 instruction in parallel when free dispatch ports available and no data dependency exist). If you load too few data into AVX512 register file with many small sequential operations and process one by one small operations it can not reach its full performance and use superscalar way of computing when possible. The AVX/AVX512 processing like to process many data and make large blocks of data stream load/store (better of cacheline granularity and aligned).
I tried to look into https://github.com/sekrit-twc/zimg/blob/master/src/zimg/colorspace/x86/operation_impl_avx512.cpp part of zimg for example and found it looks like uses very small workunit size for AVX512 and may not allow chip to make several operations dispatch in parallel because typical computing is sequential. The 'superscalarity' is sort of additional level of multithreading at neibour instructions level (close to Hyperthreading but inside single logical thread) and it also adds to performance when used properly. It not only about equal instructions performance increase - sometime you can have 2 or even more separate computing threads dispatched at the same time as single thread if free dispatch ports avaialble.
Btw using Converttorgb32() only for planar->packed causes ~30% fps drop. It seems a lot at first look. I have to test with libp2p (https://github.com/sekrit-twc/libp2p).
No speed difference.
Hehe - it looks I understand why AVS core op
YV12 -> RGB32 with ConvertToRGB32() is not fully optimized:
The operation of
ColorBars(3840, 2160, pixel_type="YV12")
ConvertToRGB32()
Is equal in speed to
ColorBars(3840, 2160, pixel_type="YV12")
ConvertToYV24()
ConvertToRGB32()
So it looks very complex Convert() core functions is sometime a sequence of Convert() so make 2 or more close to full-frame RAM scan and so performance of YV12 -> ConvertToRGB32() is 2x slower in compare with BicubicResize of 2x size for UV planes. Also performance close to independent of resampler kernel (and support) used because memory transfer penalty is main limiting speed factor. Also it somehow visibly benefit from faster RAM hosts.
The really top performance YV12 to RGB32 SIMD function in single pass (3 RAM read streams and 1 write stream) is about the next:
1. Make stream reading of Y,U,V planes parts in cacheline granularity and alignment to fill about 1/4..1/3 of registerfile of SIMD co-processor (of 512 8-bit bytes for AVX_x64 and 2048 8-bit bytes for AVX512_x64). Cached or uncached read streaming - depend on use case and current host architecture. It is user-side performance tuning setting.
2. Make upsample 2x of U V planes in registerfile only (do not touch even L1D cache).
3. Make dematrix and interleaving in registerfile only (do not touch even L1D cache).
4. Prepare write stream of cacheline granularity and alignment and emit set of store instructions to flush prepared RGB32 dataset from registerfile to memory with single dataflow burst (of about 1/2 or more of registerfile sized). Using cached or uncached write streaming to host RAM - depend on use case and host architecture. It is user-side performance tuning setting.
It is really 'hardware ASIC programming' (using handcrafted asm or C-level instruments - from inline asm to intrinsics or VCL) - not some abstract C-program.
It require to develop special SIMD program for each SIMD family and bitdepth (if >8bit support required). With very limited number of AVS core developers it is unlikely and not frequent usage YV12->RGB32 (classic interleaved) may be rarely need in top performance implementation.
AVS is freeware amateur processing software - not professional for commertial datacenter so low performance not mean low money income.
Also the planar YUV to planar RGB possibly worst performance case because or 3 read streams and 3 separate write streams.
Also it looks some nice to have feature for all AVS core filters design to user-side performance tuning - add control of caching for reading and writing. So that user can select between cached or uncached read from host RAM and write-back or uncached store to host RAM. At the architectures where we have required CPU instructions.
gispos
8th May 2023, 17:53
"with Prefetch(2) it is 78 fps,"
For your 4 core CPU optimal prefetch may be 4 (may be try a bit higher to see if there will be any visible benefit from hyperthreading).
In the script I use Prefetch(4), the Prefetch(2) has its justification.
It is about drawing the video frame in AvsPmod, ConvertToRGB is the bottleneck.
The ConvertToRGB does not benefit from the prefetch that is present in the script, because it must be derived from the clip after the script.
So this is a bit experimental and also not optimal to add a prefetch after the ConvertToRGB. This can lead to a too high prefetch value (script prefetch + RGB conversion prefetch).
Therefore only the 2.
That looks sad but fmtc also not allow to to single pass 4:2:0 to RGB conversion (fmtc_matrix require 4:4:4 input). So it looks a task to developers if some interested still exist.
"It is about drawing the video frame in AvsPmod, ConvertToRGB is the bottleneck."
May be RGB24 is enough for preview ? It may run a bit faster RGB32.
Addition: Trying to make sample plugin for YV12 to RGB24 conversion I still stuck at the colorspace change at plugin output - how it is performed ?
Is it at GetFrame() or at plugin init somewhere ?
Trying to look into avsresize.cpp at https://github.com/TomArrow/avsresize/blob/master/avsresize/avsresize.cpp but still not understand where it is switched.
When trying to create new video frame with
vi.pixel_type = CS_BGR24;
PVideoFrame dst = env->NewVideoFrame(vi);
The dst returned as RGB24 line size but VirtualDub crash at load script and avsmeter still display it is YV12 colorformat (as input). So how to make different colorspace at plugin output ?
I see a few plugins make colorformat conversion so it not very easy to find sample to modify.
That looks sad but fmtc also not allow to to single pass 4:2:0 to RGB conversion (fmtc_matrix require 4:4:4 input). So it looks a task to developers if some interested still exist.
"It is about drawing the video frame in AvsPmod, ConvertToRGB is the bottleneck."
May be RGB24 is enough for preview ? It may run a bit faster RGB32.
Addition: Trying to make sample plugin for YV12 to RGB24 conversion I still stuck at the colorspace change at plugin output - how it is performed ?
Is it at GetFrame() or at plugin init somewhere ?
Trying to look into avsresize.cpp at https://github.com/TomArrow/avsresize/blob/master/avsresize/avsresize.cpp but still not understand where it is switched.
When trying to create new video frame with
vi.pixel_type = CS_BGR24;
PVideoFrame dst = env->NewVideoFrame(vi);
The dst returned as RGB24 line size but VirtualDub crash at load script and avsmeter still display it is YV12 colorformat (as input). So how to make different colorspace at plugin output ?
I see a few plugins make colorformat conversion so it not very easy to find sample to modify.
vi.pixel_type must be set in the constructor or in the "creater", not in GetFrame.
gispos
9th May 2023, 21:42
May be RGB24 is enough for preview ? It may run a bit faster RGB32.
For videos it is probably enough, only if someone uses the alpha channel then I would have to check that and fall back to RGB32.
I think that the difference is not so big that you should do without RGB32. But if it is really faster I can live with it.
But YV12 are normally HD videos, formats of 4K videos is actually what would be of interest.
I think that will be more complex than you estimated... Thanks anyway.
FranceBB
9th May 2023, 22:48
But YV12 are normally HD videos, formats of 4K videos is actually what would be of interest.
For consumers? Still 4:2:0, but 10bit instead of 8bit and with a different chroma location (top left, aka 4:2:0 type 2) than the default MPEG-2 one (left, aka 4:2:0 type 0).
Make some tech demo of YV12 to RGB (planar only for now, RGBP8) - https://github.com/DTL2020/ConvertYV12toRGB/releases/tag/0.0.1a . AVX2 only.
It sort of draft-preview quality (using sort of point-resize for UV upsampling and completely not-aware of 'chroma-location') and 265bit regs data shuffling is not completely debugged so columns are not arranged properly. Only should run on mod64 frame widths (1920 or 3840 is good) or will not process last non-mod64 columns. Playing with 64 YUV and RGB samples at once not very easy in debugging - to place everything in correct order over scanline.
For sort of point-resize of UV plane it uses 8bit unpack with itself (single instruction) for H-scale and for V-scale it make UV line doubling in load address advancing (so it is universal 4:2:2 and 4:2:0 to RGB convert engine). So UV upscaling takes close to minimal possible time in this example.
Also can use internal OpenMP (threads) param to check AVS MT vs internal MT (not yet tested at all).
It just some quick performance test of such approach. I not have AVX2 chip at home so can not run performance test, only check if it output something like RGB decoded frame in SDE and not crash with default 640,480 frame.
Expected script for performance test is:
LoadPlugin("DecodeYV12toRGB.dll")
ColorBars(3840, 2160, pixel_type="YV12")
DecodeYV12toRGB(threads=1)
Prefetch(N) # N is number of threads, or try internal OpenMP threads at filter.
Interleaving of 32samples R, G, B AVX registers into RGB24 (or RGB32 with empty alpha) will take some more design ideas how to make it any fast. So currently planar RGB wins for processing but create 3 different store streams into RAM (though total speed is comparable to RGB24 interleaved).
Interleaving of planar RGB into RGB24 of mod3 channels step may be so SIMD-unfriendly that it may be better to do RGB32 instead.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.